You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/09/17 19:11:42 UTC

[isis] 01/02: ISIS-2433: automated gradle.settings creation (provided as JUnit test)

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 4fe19db073d607ac395960debf82fa263f61c621
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Sep 17 21:02:46 2020 +0200

    ISIS-2433: automated gradle.settings creation (provided as JUnit test)
---
 .../tooling/projectmodel/gen/GradleSettings.java   |  58 +++++++++
 .../projectmodel/gen/GradleSettingsFactory.java    |  69 ++++++++++
 .../projectmodel/gen/GradleSettingsWriter.java     |  80 ++++++++++++
 .../projectmodel/test/GradleSettingsTest.java      | 142 +++++++++++++++++++++
 4 files changed, 349 insertions(+)

diff --git a/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettings.java b/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettings.java
new file mode 100644
index 0000000..e5d37b2
--- /dev/null
+++ b/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettings.java
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.isis.tooling.projectmodel.gen;
+
+import java.io.File;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.isis.tooling.projectmodel.ArtifactKey;
+
+import lombok.Data;
+import lombok.Value;
+import lombok.val;
+
+@Data
+public class GradleSettings {
+
+    @Value(staticConstructor = "of")
+    public static class GradleBuildArtifact {
+        private final String name;
+        private final String realtivePath;
+        private final File projectDirectory;
+        
+        public final boolean isRoot() {
+            return realtivePath.equals("/");
+        }
+        
+        public final Optional<File> getDefaultBuildFile() {
+            val buildFile = new File(getProjectDirectory(), "build.gradle");
+            if(buildFile.exists()) {
+                return Optional.of(buildFile);
+            }
+            return Optional.empty();
+        }
+        
+    }
+    
+    private final String rootProjectName;
+    private final Map<ArtifactKey, GradleBuildArtifact> buildArtifactsByArtifactKey = new LinkedHashMap<>();
+    
+}
diff --git a/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettingsFactory.java b/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettingsFactory.java
new file mode 100644
index 0000000..f6f89a0
--- /dev/null
+++ b/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettingsFactory.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.isis.tooling.projectmodel.gen;
+
+import java.io.File;
+
+import org.apache.isis.commons.internal.base._Files;
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.tooling.projectmodel.ArtifactKey;
+import org.apache.isis.tooling.projectmodel.ProjectNode;
+import org.apache.isis.tooling.projectmodel.ProjectNodeFactory;
+import org.apache.isis.tooling.projectmodel.gen.GradleSettings.GradleBuildArtifact;
+
+import lombok.NonNull;
+import lombok.val;
+
+public class GradleSettingsFactory {
+
+    public static GradleSettings generateFromMaven(File projRootFolder, String rootProjectName) {
+        
+        val projTree = ProjectNodeFactory.maven(projRootFolder);
+        val rootPath = _Files.canonicalPath(projRootFolder).get();
+        
+        val gradleSettings = new GradleSettings(rootProjectName);
+        val folderByArtifactKey = gradleSettings.getBuildArtifactsByArtifactKey();
+        
+        projTree.depthFirst(projModel -> {
+            folderByArtifactKey.put(projModel.getArtifactKey(), gradleBuildArtifactFor(projModel, rootPath));
+        });
+        
+        return gradleSettings;
+    }
+    
+    // -- HELPER
+    
+    private static GradleBuildArtifact gradleBuildArtifactFor(ProjectNode projModel, String rootPath) {
+        val name = toCanonicalBuildName(projModel.getArtifactKey());
+        val realtivePath = toCanonicalRelativePath(projModel, rootPath);
+        return GradleBuildArtifact.of(name, realtivePath, projModel.getProjectDirectory());
+    }
+
+    private static String toCanonicalBuildName(final @NonNull ArtifactKey artifactKey) {
+        return String.format(":%s:%s", artifactKey.getGroupId(), artifactKey.getArtifactId());
+    }
+    
+    private static String toCanonicalRelativePath(ProjectNode projModel, String rootPath) {
+        val canonicalProjDir = _Files.canonicalPath(projModel.getProjectDirectory()).get();
+        val relativePath = _Files.toRelativePath(rootPath, canonicalProjDir);
+        return _Strings.prefix(relativePath.replace('\\', '/'), "/");
+    }
+
+    
+}
diff --git a/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettingsWriter.java b/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettingsWriter.java
new file mode 100644
index 0000000..e25d920
--- /dev/null
+++ b/tooling/projectmodel/src/main/java/org/apache/isis/tooling/projectmodel/gen/GradleSettingsWriter.java
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.isis.tooling.projectmodel.gen;
+
+import java.io.StringWriter;
+import java.io.Writer;
+
+import lombok.SneakyThrows;
+import lombok.val;
+
+public class GradleSettingsWriter {
+
+    public static String toString(GradleSettings gradleSettings) {
+        if(gradleSettings==null) {
+            return "";
+        }
+        val adocWriter = new GradleSettingsWriter();
+        val stringWriter = new StringWriter();
+        adocWriter.write(gradleSettings, stringWriter);
+        return stringWriter.toString();
+    }
+  
+    public void write(GradleSettings gradleSettings, Writer writer) {
+        writeWithFormat(writer, "rootProject.name = '%s'\n", gradleSettings.getRootProjectName());
+        
+        writeEmptyLine(writer);
+        
+        gradleSettings.getBuildArtifactsByArtifactKey().forEach((artifactKey, buildArtifact)->{
+            
+            if(buildArtifact.isRoot()) {
+                return; // don't write include statements for the project's root
+            }
+            
+            writeWithFormat(writer, "include '%s'\n", buildArtifact.getName());
+        });
+        
+        writeEmptyLine(writer);
+        
+        gradleSettings.getBuildArtifactsByArtifactKey().forEach((artifactKey, buildArtifact)->{
+            
+            if(buildArtifact.isRoot()) {
+                return; // don't write include statements for the project's root
+            }
+            
+            writeWithFormat(writer, 
+                    "project('%s').projectDir = \"$rootDir%s\" as File\n", 
+                    buildArtifact.getName(),
+                    buildArtifact.getRealtivePath());
+        });
+    }
+    
+    // -- HELPER
+    
+    @SneakyThrows
+    private static void writeWithFormat(Writer writer, String format, Object...args) {
+        writer.write(String.format(format, args));
+    }
+    
+    @SneakyThrows
+    private static void writeEmptyLine(Writer writer) {
+        writer.write("\n");
+    }
+    
+}
diff --git a/tooling/projectmodel/src/test/java/org/apache/isis/tooling/projectmodel/test/GradleSettingsTest.java b/tooling/projectmodel/src/test/java/org/apache/isis/tooling/projectmodel/test/GradleSettingsTest.java
new file mode 100644
index 0000000..04fe5aa
--- /dev/null
+++ b/tooling/projectmodel/src/test/java/org/apache/isis/tooling/projectmodel/test/GradleSettingsTest.java
@@ -0,0 +1,142 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.isis.tooling.projectmodel.test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDate;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.tooling.projectmodel.gen.GradleSettings;
+import org.apache.isis.tooling.projectmodel.gen.GradleSettingsFactory;
+import org.apache.isis.tooling.projectmodel.gen.GradleSettingsWriter;
+
+import lombok.SneakyThrows;
+import lombok.val;
+
+class GradleSettingsTest {
+
+    File projRootFolder;
+    boolean hasUnresolvableGradleBuildArtifacts;
+    
+    @BeforeEach
+    void setUp() throws Exception {
+        projRootFolder = new File("./").getAbsoluteFile().getParentFile().getParentFile().getParentFile();
+        System.out.println("running GradleSettingsTest at " + projRootFolder.getAbsolutePath());
+        hasUnresolvableGradleBuildArtifacts = false;
+    }
+
+    @AfterEach
+    void tearDown() throws Exception {
+    }
+
+    @Test @Disabled("activate only if you want to see the settings.gradle written to stdout")
+    void writeGradleSettingsToStdout() throws IOException {
+        GradleSettings gradleSettings = GradleSettingsFactory.generateFromMaven(projRootFolder, "isis");
+        assertNotNull(gradleSettings);
+        
+        System.out.println();
+        System.out.println();
+        System.out.println(String.format("// generated by %s", this.getClass().getName()));
+        System.out.println(String.format("// date %s", LocalDate.now().toString()));
+        System.out.println();
+        System.out.println(GradleSettingsWriter.toString(gradleSettings));
+    }
+    
+    @Test
+    void testGradleSettingGenerator() throws IOException {
+        GradleSettings gradleSettings = GradleSettingsFactory.generateFromMaven(projRootFolder, "isis");
+        
+        assertNotNull(gradleSettings);
+        
+        val knownBuildArtifactNames = new HashSet<String>();
+        
+        gradleSettings.getBuildArtifactsByArtifactKey().forEach((artifactKey, buildArtifact)->{
+            knownBuildArtifactNames.add(buildArtifact.getName());
+        });
+        
+        gradleSettings.getBuildArtifactsByArtifactKey().forEach((artifactKey, buildArtifact)->{
+            
+            if(buildArtifact.isRoot()) {
+                return; // skip project's root
+            }
+
+            buildArtifact.getDefaultBuildFile()
+            .ifPresent(buildFile->{
+                checkBuildFile(buildFile, knownBuildArtifactNames);
+            });
+            
+        });
+        
+        assertFalse(hasUnresolvableGradleBuildArtifacts);
+    }
+    
+    // -- HELPER
+
+    @SneakyThrows
+    private void checkBuildFile(File buildFile, Set<String> knownBuildArtifactNames) {
+        //System.out.println(String.format("checking %s", buildFile.getAbsolutePath()));
+        
+        val lines = _Strings.readAllLines(new FileInputStream(buildFile), StandardCharsets.UTF_8);
+        
+        for(val line : lines) {
+            checkBuildFileLine(buildFile, line, knownBuildArtifactNames);
+        }
+        
+    }
+
+    private void checkBuildFileLine(File buildFile, String line, Set<String> knownBuildArtifactNames) {
+        val buildArtifactName = parseBuildArtifactName(line);
+        if(buildArtifactName==null) {
+            return;
+        }
+        if(!knownBuildArtifactNames.contains(buildArtifactName)) {
+            hasUnresolvableGradleBuildArtifacts = true;
+            System.err.println(String.format("not found '%s' in file '%s'", buildArtifactName, buildFile));
+        }
+    }
+    
+    //    compile project(':isis-parent:isis-schema')
+    private String parseBuildArtifactName(String line) {
+        int p = line.indexOf("project('");
+        if(p<0) {
+            return null;
+        }
+        int start = p + 9;
+        int end = line.indexOf("')", start);
+        if(end<0) {
+            return null;
+        }
+        val buildArtifactName = line.substring(start, end);
+        return buildArtifactName;
+    }
+    
+}