You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2020/11/01 21:55:13 UTC
[tapestry-5] branch java9modules updated: TAP5-2641: first working
version of migrator tool
This is an automated email from the ASF dual-hosted git repository.
thiagohp pushed a commit to branch java9modules
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
The following commit(s) were added to refs/heads/java9modules by this push:
new f293fff TAP5-2641: first working version of migrator tool
f293fff is described below
commit f293fffb28e69c2571ebe257d514a5781b268a56
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
AuthorDate: Sun Nov 1 18:50:33 2020 -0300
TAP5-2641: first working version of migrator tool
---
tapestry-version-migrator/build.gradle | 11 +-
.../tapestry5/versionmigrator/ClassRefactor.java | 135 ++++++++++
.../versionmigrator/FileRefactorCommitParser.java | 45 ++++
.../org/apache/tapestry5/versionmigrator/Main.java | 280 +++++++++++++++++++--
.../tapestry5/versionmigrator/TapestryVersion.java | 5 +
.../ArtifactChangeRefactorCommitParser.java | 49 ++++
...ckageAndArtifactChangeRefactorCommitParser.java | 55 ++++
.../PackageChangeRefactorCommitParser.java | 57 +++++
.../tapestry5/versionmigrator/5.7.0.properties | 129 ++++++++++
.../versionmigrator/change-report-5.7.0.html | 1 +
.../versionmigrator/ClassRefactorTest.java | 112 +++++++++
.../ArtifactChangeRefactorCommitParserTest.java | 41 +++
...eAndArtifactChangeRefactorCommitParserTest.java | 40 +++
.../PackageChangeRefactorCommitParserTest.java | 40 +++
.../test-sources/ClassAtRootFolder.java | 11 +
.../subfolder/subsubfolder/ClassAtSubFolder.java | 15 ++
16 files changed, 997 insertions(+), 29 deletions(-)
diff --git a/tapestry-version-migrator/build.gradle b/tapestry-version-migrator/build.gradle
index 50ffffe..8769d68 100644
--- a/tapestry-version-migrator/build.gradle
+++ b/tapestry-version-migrator/build.gradle
@@ -1,14 +1,17 @@
description = "Tool to help migrate source code using Tapestry from one version to another. Initially built for 5.7.0"
dependencies {
+ testCompile group: 'org.testng', name: 'testng', version: '7.3.0'
}
test {
- useJUnit()
+ useTestNG() {
+ useDefaultListeners = true // Tells TestNG to execute its default reporting structure
+ }
}
-/*jar {
+jar {
manifest {
- attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.json.modules.JSONModule'
+ attributes 'Main-Class': 'org.apache.tapestry5.versionmigrator.Main'
}
-}*/
+}
diff --git a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/ClassRefactor.java b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/ClassRefactor.java
new file mode 100644
index 0000000..5cd2e9c
--- /dev/null
+++ b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/ClassRefactor.java
@@ -0,0 +1,135 @@
+// 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.apache.tapestry5.versionmigrator;
+
+/**
+ * Class that represents information about one class being renamed and/or moved
+ * between artifacts (JARs) and/or packages.
+ */
+final public class ClassRefactor
+{
+
+ final private String newClassName;
+ final private String oldClassName;
+ final private String sourceArtifact;
+ final private String destinationArtifact;
+
+ /**
+ * Constructor for classes being moved from one artifact to another
+ * and possibly being renamed or moved between packages.
+ */
+ public ClassRefactor(String newClassName, String oldClassName, String sourceArtifact, String destinationArtifact)
+ {
+ super();
+ verifyNotBlank("newClassName", newClassName);
+ verifyNotBlank("oldClassName", oldClassName);
+ verifyNotBlank("sourceArtifact", sourceArtifact);
+ verifyNotBlank("destinationArtifact", destinationArtifact);
+ this.newClassName = newClassName;
+ this.oldClassName = oldClassName;
+ this.sourceArtifact = sourceArtifact;
+ this.destinationArtifact = destinationArtifact;
+ }
+
+ /**
+ * Returns the new fully-qualified class name.
+ */
+ public String getNewClassName()
+ {
+ return newClassName;
+ }
+
+ /**
+ * Returns the old fully-qualified class name.
+ */
+ public String getOldClassName()
+ {
+ return oldClassName;
+ }
+
+ /**
+ * Returns the artifact where the class was located.
+ */
+ public String getSourceArtifact()
+ {
+ return sourceArtifact;
+ }
+
+ /**
+ * Returns the artifact where the class is now located.
+ */
+ public String getDestinationArtifact()
+ {
+ return destinationArtifact;
+ }
+
+ /**
+ * Returns whether the class was moved between artifacts.
+ */
+ public boolean isMovedBetweenArtifacts()
+ {
+ return !sourceArtifact.equals(destinationArtifact);
+ }
+
+ /**
+ * Returns whether the class had its fully qualified class name changed.
+ * This includes package changes.
+ */
+ public boolean isRenamed()
+ {
+ return !oldClassName.equals(newClassName);
+ }
+
+ @Override
+ public String toString() {
+ return "ClassMoveInformation [newClassName=" + newClassName + ", oldClassName=" + oldClassName + ", sourceArtifact=" + sourceArtifact
+ + ", destinationArtifact=" + destinationArtifact + "]";
+ }
+
+ final static boolean isNotBlank(String string)
+ {
+ return string != null && string.trim().length() > 0;
+ }
+
+ final static void verifyNotBlank(String parameterName, String parameterValue)
+ {
+ if (!isNotBlank(parameterValue))
+ {
+ throw new IllegalArgumentException(
+ String.format("Parameter %s cannot be null nor blank", parameterName));
+ }
+ }
+
+ /**
+ * Returns the simple old class name.
+ */
+ public String getSimpleOldClassName() {
+ return oldClassName.substring(oldClassName.lastIndexOf(".") + 1);
+ }
+
+ /**
+ * Returns whether the class is internal or not.
+ */
+ public boolean isInternal()
+ {
+ return oldClassName.contains(".internal.");
+ }
+
+ /**
+ * Returns the new package location.
+ */
+ public String getNewPackageName()
+ {
+ return newClassName.substring(0, newClassName.lastIndexOf("."));
+ }
+
+}
\ No newline at end of file
diff --git a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/FileRefactorCommitParser.java b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/FileRefactorCommitParser.java
new file mode 100644
index 0000000..f6bd9c9
--- /dev/null
+++ b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/FileRefactorCommitParser.java
@@ -0,0 +1,45 @@
+// 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.apache.tapestry5.versionmigrator;
+
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.regex.Pattern;
+
+/**
+ * Interface that defines a file refactor parser.
+ */
+public interface FileRefactorCommitParser extends Function<String, Optional<ClassRefactor>>
+{
+ /**
+ * Extracts a package or class name from a string which may contain <code>src/main/java/</code>
+ * or <code>src/test/java/</code>
+ */
+ static String extractPackageOrClassName(String string)
+ {
+ return string
+ .replace("src/main/java/", "")
+ .replace("src/test/java/", "")
+ .replace("/", ".");
+ }
+
+ /**
+ * Builds a class name given some parts.
+ */
+ static String buildClassName(final String rootPackageName, String packageNameSuffix, final String className)
+ {
+ return (rootPackageName + packageNameSuffix.replace("/", ".") + "." + className.replace("/", "."))
+ .replaceAll(Pattern.quote(".."), ".");
+ }
+
+
+}
diff --git a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/Main.java b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/Main.java
index b1b07dc..48dc5ba 100644
--- a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/Main.java
+++ b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/Main.java
@@ -11,21 +11,31 @@
// limitations under the License.
package org.apache.tapestry5.versionmigrator;
+import java.io.BufferedOutputStream;
import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.io.StringWriter;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
+import java.util.Comparator;
+import java.util.Formatter;
import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
+import org.apache.tapestry5.versionmigrator.internal.ArtifactChangeRefactorCommitParser;
+import org.apache.tapestry5.versionmigrator.internal.PackageAndArtifactChangeRefactorCommitParser;
+import org.apache.tapestry5.versionmigrator.internal.PackageChangeRefactorCommitParser;
+
public class Main
{
@@ -37,10 +47,15 @@ public class Main
}
else
{
+ TapestryVersion version = getTapestryVersion(args[1]);
switch (args[0])
{
case "generate":
- createVersionFile(args[1]);
+ createVersionFile(version);
+ break;
+
+ case "upgrade":
+ upgrade(version);
break;
default:
@@ -49,26 +64,116 @@ public class Main
}
}
- private static void printHelp() {
- // TODO Auto-generated method stub
+ private static void upgrade(TapestryVersion version)
+ {
+
+ String path = "/" + getFileRelativePath(getSimpleFileName(version));
+ Properties properties = new Properties();
+ try (InputStream inputStream = Main.class.getResourceAsStream(path))
+ {
+ properties.load(inputStream);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ List<File> javaFiles = getJavaFiles();
+
+ System.out.println("Number of renamed or moved classes: " + properties.size());
+ System.out.println("Number of Java source files found: " + javaFiles.size());
+
+ int totalCount = 0;
+ int totalChanged = 0;
+ for (File file : javaFiles)
+ {
+ boolean changed = upgrade(file, properties);
+ if (changed) {
+ totalChanged++;
+ try {
+ System.out.println("Changed and upgraded file " + file.getCanonicalPath());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ totalCount++;
+ if (totalCount % 100 == 0)
+ {
+ System.out.printf("Processed %5d out of %d files (%.1f%%)\n",
+ totalCount, javaFiles.size(), totalCount * 100.0 / javaFiles.size());
+ }
+ }
+
+ System.out.printf("Upgrade finished successfully. %s files changed out of %s.", totalChanged, totalCount);
}
+
+ private static boolean upgrade(File file, Properties properties)
+ {
+ Path path = Paths.get(file.toURI());
+ String content;
+ boolean changed = false;
+ try {
+ content = new String(Files.readAllBytes(path));
+ String newContent = content;
+ String newClassName;
+ for (String oldClassName : properties.stringPropertyNames())
+ {
+ newClassName = properties.getProperty(oldClassName);
+ newContent = newContent.replace(oldClassName, newClassName);
+ }
+ if (!newContent.equals(content))
+ {
+ changed = true;
+ Files.write(path, newContent.getBytes());
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return changed;
+ }
+
+ private static List<File> getJavaFiles()
+ {
+ ArrayList<File> files = new ArrayList<>();
+ collectJavaFiles(new File("."), files);
+ return files;
+ }
+
+ private static void collectJavaFiles(File currentFolder, List<File> javaFiles)
+ {
+ File[] javaFilesInFolder = currentFolder.listFiles((f) -> f.isFile() && f.getName().endsWith(".java"));
+ for (File file : javaFilesInFolder) {
+ javaFiles.add(file);
+ }
+ File[] subfolders = currentFolder.listFiles((f) -> f.isDirectory());
+ for (File subfolder : subfolders) {
+ collectJavaFiles(subfolder, javaFiles);
+ }
+ }
- private static void createVersionFile(String versionNumber)
+ private static void printHelp()
{
+ System.out.println("Apache Tapestry version migrator options:");
+ System.out.println("\t upgrade [version number]: updates references to classes which have been moved or renamed in Java source files in the current folder and its subfolders.");
+ System.out.println("\t generate [version number]: analyzes version control and outputs information about moved classes.");
+ System.out.println("Apache Tapestry versions available in this tool: " +
+ Arrays.stream(TapestryVersion.values())
+ .map(TapestryVersion::getNumber)
+ .collect(Collectors.joining(", ")));
+ }
+
+ private static TapestryVersion getTapestryVersion(String versionNumber) {
final TapestryVersion tapestryVersion = Arrays.stream(TapestryVersion.values())
.filter(v -> versionNumber.equals(v.getNumber()))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unknown Tapestry version: " + versionNumber + ". "));
- createVersionFile(tapestryVersion);
+ return tapestryVersion;
}
-
+
private static void createVersionFile(TapestryVersion version)
{
final String commandLine = String.format("git diff --summary %s %s",
version.getPreviousVersionGitHash(), version.getVersionGitHash());
final Process process;
- final Map<String, String> renames = new HashMap<>();
System.out.printf("Running command line '%s'\n", commandLine);
List<String> lines = new ArrayList<>();
@@ -92,31 +197,156 @@ public class Main
} catch (IOException e) {
throw new RuntimeException(e);
}
- process(lines, renames);
+ List<ClassRefactor> refactors = parse(lines);
+ AtomicInteger packageChange = new AtomicInteger();
+ AtomicInteger artifactChange = new AtomicInteger();
+ AtomicInteger packageAndArtifactChange = new AtomicInteger();
+
+ refactors.stream().forEach(r -> {
+ if (r.isMovedBetweenArtifacts() && r.isRenamed()) {
+ packageAndArtifactChange.incrementAndGet();
+ }
+ if (r.isMovedBetweenArtifacts()) {
+ artifactChange.incrementAndGet();
+ }
+ if (r.isRenamed()) {
+ packageChange.incrementAndGet();
+ }
+ });
+
+ System.out.println("Stats:");
+ System.out.printf("\t%d classes changed package or artifact\n", refactors.size());
+ System.out.printf("\t%d classes changed packages\n", packageChange.get());
+ System.out.printf("\t%d classes changed artifacts\n", artifactChange.get());
+ System.out.printf("\t%d classes changed both package and artifact\n", packageAndArtifactChange.get());
+
+ writeVersionFile(version, refactors);
+ writeRefactorsFile(version, refactors);
+ }
+
+ private static void writeRefactorsFile(TapestryVersion version, List<ClassRefactor> refactors)
+ {
+ File file = getFile("change-report-" + version.getNumber() + ".html");
+ List<ClassRefactor> sorted = new ArrayList<>(refactors);
+ sorted.sort(Comparator.comparing(
+ ClassRefactor::isInternal).thenComparing(
+ ClassRefactor::getSimpleOldClassName));
+ try (Formatter formatter = new Formatter(file))
+ {
+ formatter.format("<html>");
+ formatter.format("\t<head>");
+ formatter.format("\t\t<title>Changes introduced in Apache Tapestry %s</title>", version.getNumber());
+ formatter.format("\t</head>");
+ formatter.format("\t<body>");
+ formatter.format("\t\t<table>");
+ formatter.format("\t\t\t<thead>");
+ formatter.format("\t\t\t\t<th>Old class name</th>");
+ formatter.format("\t\t\t\t<th>Renamed or moved?</th>");
+ formatter.format("\t\t\t\t<th>New package location</th>");
+ formatter.format("\t\t\t\t<th>Moved artifacts?</th>");
+ formatter.format("\t\t\t\t<th>Old artifact location</th>");
+ formatter.format("\t\t\t\t<th>New artifact location</th>");
+ formatter.format("\t\t\t</thead>");
+ formatter.format("\t\t\t<tbody>");
+ sorted.stream().forEach(r -> {
+ formatter.format("\t\t\t\t<tr>");
+ formatter.format("\t\t\t\t\t<td>%s</td>", r.getSimpleOldClassName());
+ boolean renamed = r.isRenamed();
+ boolean movedBetweenArtifacts = r.isMovedBetweenArtifacts();
+ formatter.format("\t\t\t\t\t<td>%s</td>", renamed ? "yes" : "no");
+ formatter.format("\t\t\t\t\t<td>%s</td>", renamed ? r.getNewPackageName() : "");
+ formatter.format("\t\t\t\t\t<td>%s</td>", movedBetweenArtifacts ? "yes" : "no");
+ formatter.format("\t\t\t\t\t<td>%s</td>", movedBetweenArtifacts ? r.getSourceArtifact() : "");
+ formatter.format("\t\t\t\t\t<td>%s</td>", movedBetweenArtifacts ? r.getDestinationArtifact() : "");
+ formatter.format("\t\t\t\t\t</tr>");
+ });
+ formatter.format("\t\t\t</tbody>");
+ formatter.format("\t\t</table>");
+ formatter.format("\t</body>");
+ formatter.format("</html>");
+ System.out.println("Change report file successfully written to " + file.getAbsolutePath());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void writeVersionFile(TapestryVersion version, List<ClassRefactor> refactors)
+ {
+ Properties properties = new Properties();
+ refactors.stream()
+ .filter(ClassRefactor::isRenamed)
+ .forEach(r -> properties.setProperty(r.getOldClassName(), r.getNewClassName()));
+
+ final File file = getChangesFile(version);
+ try (
+ OutputStream outputStream = new FileOutputStream(file);
+ BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream))
+ {
+ properties.store(bufferedOutputStream, version.toString());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ System.out.println("Version file successfully written to " + file.getAbsolutePath());
+ }
+
+ private static File getChangesFile(TapestryVersion version) {
+ String filename = getSimpleFileName(version);
+ final File file = getFile(filename);
+ return file;
+ }
+
+ private static String getSimpleFileName(TapestryVersion version) {
+ return version.getNumber() + ".properties";
+ }
+
+ private static File getFile(String filename) {
+ final String fileRelativePath = getFileRelativePath(filename);
+ final File file = new File("src/main/resources/" + fileRelativePath);
+ file.getParentFile().mkdirs();
+ return file;
}
- private static void process(List<String> lines, Map<String, String> renames) {
+ private static String getFileRelativePath(String filename) {
+ final String fileRelativePath =
+ Main.class.getPackage().getName().replace('.', '/')
+ + "/" + filename;
+ return fileRelativePath;
+ }
+
+ private static List<ClassRefactor> parse(List<String> lines)
+ {
+ System.out.println("Lines to process: " + lines.size());
+
lines = lines.stream()
.map(s -> s.trim())
.filter(s -> s.startsWith("rename"))
.filter(s -> !s.contains("test"))
.filter(s -> !s.contains("package-info"))
+ .filter(s -> !s.contains("/resources/"))
+ .filter(s -> !s.contains("/filtered-resources/"))
.map(s -> s.replaceFirst("rename", "").trim())
.collect(Collectors.toList());
- for (String line : lines) {
- if (line.startsWith("{")) {
-
+ List<ClassRefactor> refactors = new ArrayList<>(lines.size());
+
+ for (String line : lines)
+ {
+ PackageAndArtifactChangeRefactorCommitParser packageAndArtifactParser = new PackageAndArtifactChangeRefactorCommitParser();
+ ArtifactChangeRefactorCommitParser artifactParser = new ArtifactChangeRefactorCommitParser();
+ PackageChangeRefactorCommitParser packageParser = new PackageChangeRefactorCommitParser();
+ Optional<ClassRefactor> maybeMove = packageAndArtifactParser.apply(line);
+ if (!maybeMove.isPresent()) {
+ maybeMove = packageParser.apply(line);
}
- else {
- Pattern pattern = Pattern.compile("([^/]*)" + Pattern.quote("/") + "(.*)" + Pattern.quote("{") + "(.*)\\s=>\\s(.*)" + Pattern.quote("}/") + "([^\\.]*).*");
-
- final Matcher matcher = pattern.matcher(line);
- if (matcher.matches()) {
- System.out.printf("%s %s %s %s %s\n", matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4), matcher.group(5));
- }
+ if (!maybeMove.isPresent()) {
+ maybeMove = artifactParser.apply(line);
}
+ ClassRefactor move = maybeMove.orElseThrow(() -> new RuntimeException("Commit not handled: " + line));
+ refactors.add(move);
}
+
+ return refactors;
+
}
}
diff --git a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/TapestryVersion.java b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/TapestryVersion.java
index ea316b7..3a01e41 100644
--- a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/TapestryVersion.java
+++ b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/TapestryVersion.java
@@ -55,5 +55,10 @@ public enum TapestryVersion
{
return versionGitHash;
}
+
+ public String toString()
+ {
+ return String.format("Apache Tapestry %s", getNumber());
+ }
}
\ No newline at end of file
diff --git a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/ArtifactChangeRefactorCommitParser.java b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/ArtifactChangeRefactorCommitParser.java
new file mode 100644
index 0000000..d51e1ef
--- /dev/null
+++ b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/ArtifactChangeRefactorCommitParser.java
@@ -0,0 +1,49 @@
+// 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.apache.tapestry5.versionmigrator.internal;
+
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.tapestry5.versionmigrator.ClassRefactor;
+import org.apache.tapestry5.versionmigrator.FileRefactorCommitParser;
+
+/**
+ * Parses lines like this, in which just the artifact is changed:
+ * <code>{tapestry-ioc => tapestry5-annotations}/src/main/java/org/apache/tapestry5/ioc/annotations/Advise.java (100%)</code>.
+ */
+public class ArtifactChangeRefactorCommitParser implements FileRefactorCommitParser {
+
+ final public static String EXAMPLE = "{tapestry-ioc => tapestry5-annotations}/src/main/java/org/apache/tapestry5/ioc/annotations/Advise.java";
+
+ final private static Pattern PATTERN =
+ Pattern.compile("\\{(.*)\\s=>\\s([^}]*)}\\/([^\\.]*).*");
+
+ @Override
+ public Optional<ClassRefactor> apply(String line) {
+ final Matcher matcher = PATTERN.matcher(line);
+ ClassRefactor move = null;
+ if (matcher.matches())
+ {
+// System.out.printf("1(%s) 2(%s) 3(%s)\n", otherMatcher.group(1), otherMatcher.group(2), otherMatcher.group(3));
+ final String className = FileRefactorCommitParser.extractPackageOrClassName(matcher.group(3));
+ final String sourceArtifactName = matcher.group(1);
+ final String destinationArtifactName = matcher.group(2);
+
+ move = new ClassRefactor(className, className, sourceArtifactName, destinationArtifactName);
+ }
+ return Optional.ofNullable(move);
+ }
+
+}
diff --git a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/PackageAndArtifactChangeRefactorCommitParser.java b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/PackageAndArtifactChangeRefactorCommitParser.java
new file mode 100644
index 0000000..e8598a9
--- /dev/null
+++ b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/PackageAndArtifactChangeRefactorCommitParser.java
@@ -0,0 +1,55 @@
+// 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.apache.tapestry5.versionmigrator.internal;
+
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.tapestry5.versionmigrator.ClassRefactor;
+import org.apache.tapestry5.versionmigrator.FileRefactorCommitParser;
+
+/**
+ * Parses lines like this, in which both artifact and package are changed:
+ * <code>{tapestry-ioc/src/main/java/org/apache/tapestry5/ioc => commons/src/main/java/org/apache/tapestry5/commons}/ObjectProvider.java</code>.
+ */
+public class PackageAndArtifactChangeRefactorCommitParser implements FileRefactorCommitParser {
+
+ final public static String EXAMPLE = "{tapestry-ioc/src/main/java/org/apache/tapestry5/ioc => commons/src/main/java/org/apache/tapestry5/commons}/ObjectProvider.java";
+
+ final private static Pattern PATTERN =
+ Pattern.compile("\\{([^\\/]+)\\/([^\\s]+)\\s=>\\s([^\\/]+)\\/([^}]+)}([^\\.]+).*");
+
+ @Override
+ public Optional<ClassRefactor> apply(String line)
+ {
+ ClassRefactor move = null;
+ final Matcher matcher = PATTERN.matcher(line);
+ if (matcher.matches())
+ {
+// System.out.printf("1(%s) 2(%s) 3(%s) 4(%s) 5(%s)\n", matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4), matcher.group(5));
+ String newPackageNameSuffix = FileRefactorCommitParser.extractPackageOrClassName(matcher.group(4));
+ String oldPackageNameSuffix = FileRefactorCommitParser.extractPackageOrClassName(matcher.group(2));
+ final String className = matcher.group(5);
+ final String newClassName = FileRefactorCommitParser.buildClassName("", newPackageNameSuffix, className);
+ final String oldClassName = FileRefactorCommitParser.buildClassName("", oldPackageNameSuffix, className);
+ final String sourceArtifactName = matcher.group(1);
+ final String destinationArtifactName = matcher.group(3);
+
+ move = new ClassRefactor(newClassName, oldClassName, sourceArtifactName, destinationArtifactName);
+ }
+ return Optional.ofNullable(move);
+
+ }
+
+}
diff --git a/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/PackageChangeRefactorCommitParser.java b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/PackageChangeRefactorCommitParser.java
new file mode 100644
index 0000000..d751632
--- /dev/null
+++ b/tapestry-version-migrator/src/main/java/org/apache/tapestry5/versionmigrator/internal/PackageChangeRefactorCommitParser.java
@@ -0,0 +1,57 @@
+// 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.apache.tapestry5.versionmigrator.internal;
+
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.tapestry5.versionmigrator.ClassRefactor;
+import org.apache.tapestry5.versionmigrator.FileRefactorCommitParser;
+
+/**
+ * Parses lines like this, in which just the package is changed:
+ * <code>commons/src/main/java/org/apache/tapestry5/{ioc => commons}/Messages.java (98%)</code>.
+ */
+public class PackageChangeRefactorCommitParser implements FileRefactorCommitParser {
+
+ final public static String EXAMPLE = "commons/src/main/java/org/apache/tapestry5/{ioc => commons}/Messages.java (98%)";
+
+ final private static Pattern PATTERN =
+ Pattern.compile("([^/]*)/(.*)" + Pattern.quote("{") + "(.*)\\s=>\\s(.*)" + Pattern.quote("}/") + "([^\\.]*).*");
+
+ @Override
+ public Optional<ClassRefactor> apply(String line)
+ {
+ final Matcher matcher = PATTERN.matcher(line);
+ ClassRefactor move = null;
+ if (matcher.matches())
+ {
+ String newPackageNameSuffix = matcher.group(4);
+ String oldPackageNameSuffix = matcher.group(3);
+// System.out.printf("1(%s) 2(%s) 3(%s) 4(%s) 5(%s)\n", matcher.group(1), matcher.group(2), oldPackageNameSuffix, newPackageNameSuffix, matcher.group(5));
+
+ final String rootPackageName = matcher.group(2)
+ .replace("src/main/java/", "")
+ .replace("/", ".");
+ final String className = matcher.group(5);
+ final String newClassName = FileRefactorCommitParser.buildClassName(rootPackageName, newPackageNameSuffix, className);
+ final String oldClassName = FileRefactorCommitParser.buildClassName(rootPackageName, oldPackageNameSuffix, className);
+ final String artifactName = matcher.group(1);
+
+ move = new ClassRefactor(newClassName, oldClassName, artifactName, artifactName);
+ }
+ return Optional.ofNullable(move);
+ }
+
+}
diff --git a/tapestry-version-migrator/src/main/resources/org/apache/tapestry5/versionmigrator/5.7.0.properties b/tapestry-version-migrator/src/main/resources/org/apache/tapestry5/versionmigrator/5.7.0.properties
new file mode 100644
index 0000000..27b8719
--- /dev/null
+++ b/tapestry-version-migrator/src/main/resources/org/apache/tapestry5/versionmigrator/5.7.0.properties
@@ -0,0 +1,129 @@
+#Apache Tapestry 5.7.0
+#Sun Nov 01 10:43:36 BRT 2020
+org.apache.tapestry5.Link=org.apache.tapestry5.http.Link
+org.apache.tapestry5.ioc.internal.services.CompoundCoercion=org.apache.tapestry5.commons.internal.services.CompoundCoercion
+org.apache.tapestry5.internal.hibernate.PersistedTransientEntity=org.apache.tapestry5.hibernate.web.internal.PersistedTransientEntity
+org.apache.tapestry5.ioc.MessageFormatter=org.apache.tapestry5.commons.MessageFormatter
+org.apache.tapestry5.internal.hibernate.SessionRestorable=org.apache.tapestry5.hibernate.web.internal.SessionRestorable
+org.apache.tapestry5.ioc.OrderedConfiguration=org.apache.tapestry5.commons.OrderedConfiguration
+org.apache.tapestry5.internal.SyntheticSymbolSourceContributionDef=org.apache.tapestry5.http.internal.SyntheticSymbolSourceContributionDef
+org.apache.tapestry5.services.GenericsResolver=org.apache.tapestry5.commons.services.GenericsResolver
+org.apache.tapestry5.ioc.util.StrategyRegistry=org.apache.tapestry5.commons.util.StrategyRegistry
+org.apache.tapestry5.internal.ServletContextSymbolProvider=org.apache.tapestry5.http.internal.ServletContextSymbolProvider
+org.apache.tapestry5.ioc.services.Coercion=org.apache.tapestry5.commons.services.Coercion
+org.apache.tapestry5.ContentType=org.apache.tapestry5.http.ContentType
+org.apache.tapestry5.ioc.internal.services.ServiceMessages=org.apache.tapestry5.commons.internal.services.ServiceMessages
+org.apache.tapestry5.ioc.ObjectProvider=org.apache.tapestry5.commons.ObjectProvider
+org.apache.tapestry5.internal.hibernate.HibernateEntityValueEncoder=org.apache.tapestry5.hibernate.web.internal.HibernateEntityValueEncoder
+org.apache.tapestry5.internal.hibernate.PersistedEntity=org.apache.tapestry5.hibernate.web.internal.PersistedEntity
+org.apache.tapestry5.ioc.util.ExceptionUtils=org.apache.tapestry5.commons.util.ExceptionUtils
+org.apache.tapestry5.ioc.internal.BasicDataTypeAnalyzers=org.apache.tapestry5.commons.internal.BasicDataTypeAnalyzers
+org.apache.tapestry5.services.Context=org.apache.tapestry5.http.services.Context
+org.apache.tapestry5.hibernate.HibernatePersistenceConstants=org.apache.tapestry5.hibernate.web.HibernatePersistenceConstants
+org.apache.tapestry5.internal.services.RequestImpl=org.apache.tapestry5.http.internal.services.RequestImpl
+org.apache.tapestry5.internal.services.OptimizedSessionPersistedObjectAnalyzer=org.apache.tapestry5.http.internal.services.OptimizedSessionPersistedObjectAnalyzer
+org.apache.tapestry5.ioc.Configuration=org.apache.tapestry5.commons.Configuration
+org.apache.tapestry5.services.Session=org.apache.tapestry5.http.services.Session
+org.apache.tapestry5.services.Request=org.apache.tapestry5.http.services.Request
+org.apache.tapestry5.internal.services.ResponseImpl=org.apache.tapestry5.http.internal.services.ResponseImpl
+org.apache.tapestry5.internal.services.ResponseCompressionAnalyzerImpl=org.apache.tapestry5.http.internal.services.ResponseCompressionAnalyzerImpl
+org.apache.tapestry5.services.RequestFilter=org.apache.tapestry5.http.services.RequestFilter
+org.apache.tapestry5.ioc.internal.services.AnnotationProviderChain=org.apache.tapestry5.commons.internal.services.AnnotationProviderChain
+org.apache.tapestry5.services.HttpServletRequestHandler=org.apache.tapestry5.http.services.HttpServletRequestHandler
+org.apache.tapestry5.internal.util.MultiKey=org.apache.tapestry5.commons.util.MultiKey
+org.apache.tapestry5.services.ApplicationGlobals=org.apache.tapestry5.http.services.ApplicationGlobals
+org.apache.tapestry5.services.RequestGlobals=org.apache.tapestry5.http.services.RequestGlobals
+org.apache.tapestry5.internal.util.IntegerRange=org.apache.tapestry5.commons.util.IntegerRange
+org.apache.tapestry5.services.Response=org.apache.tapestry5.http.services.Response
+org.apache.tapestry5.internal.hibernate.HibernateSessionManagerImpl=org.apache.tapestry5.hibernate.internal.HibernateSessionManagerImpl
+org.apache.tapestry5.internal.services.StringInternerImpl=org.apache.tapestry5.commons.internal.services.StringInternerImpl
+org.apache.tapestry5.internal.hibernate.DefaultHibernateConfigurer=org.apache.tapestry5.hibernate.internal.DefaultHibernateConfigurer
+org.apache.tapestry5.ioc.MappedConfiguration=org.apache.tapestry5.commons.MappedConfiguration
+org.apache.tapestry5.services.ServletApplicationInitializerFilter=org.apache.tapestry5.http.services.ServletApplicationInitializerFilter
+org.apache.tapestry5.internal.genericsresolverguava.GuavaGenericsResolver=org.apache.tapestry5.genericsresolverguava.internal.GuavaGenericsResolver
+org.apache.tapestry5.ioc.services.PropertyAdapter=org.apache.tapestry5.commons.services.PropertyAdapter
+org.apache.tapestry5.LinkSecurity=org.apache.tapestry5.http.LinkSecurity
+org.apache.tapestry5.ioc.internal.util.MessagesImpl=org.apache.tapestry5.commons.internal.util.MessagesImpl
+org.apache.tapestry5.ioc.services.PropertyAccess=org.apache.tapestry5.commons.services.PropertyAccess
+org.apache.tapestry5.internal.hibernate.HibernateSessionSourceImpl=org.apache.tapestry5.hibernate.internal.HibernateSessionSourceImpl
+org.apache.tapestry5.services.Dispatcher=org.apache.tapestry5.http.services.Dispatcher
+org.apache.tapestry5.services.ComponentLayer=org.apache.tapestry5.ioc.annotations.ComponentLayer
+org.apache.tapestry5.ioc.internal.util.InternalCommonsUtils=org.apache.tapestry5.commons.internal.util.InternalCommonsUtils
+org.apache.tapestry5.services.ComponentClasses=org.apache.tapestry5.ioc.annotations.ComponentClasses
+org.apache.tapestry5.internal.services.TapestrySessionFactory=org.apache.tapestry5.http.internal.services.TapestrySessionFactory
+org.apache.tapestry5.hibernate.modules.HibernateModule=org.apache.tapestry5.hibernate.web.modules.HibernateModule
+org.apache.tapestry5.internal.services.SessionImpl=org.apache.tapestry5.http.internal.services.SessionImpl
+org.apache.tapestry5.ioc.AnnotationProvider=org.apache.tapestry5.commons.AnnotationProvider
+org.apache.tapestry5.ioc.internal.BasicTypeCoercions=org.apache.tapestry5.commons.internal.BasicTypeCoercions
+org.apache.tapestry5.services.RequestHandler=org.apache.tapestry5.http.services.RequestHandler
+org.apache.tapestry5.internal.hibernate.HibernateTransactionAdvisorImpl=org.apache.tapestry5.hibernate.internal.HibernateTransactionAdvisorImpl
+org.apache.tapestry5.ioc.Messages=org.apache.tapestry5.commons.Messages
+org.apache.tapestry5.ioc.internal.util.CollectionFactory=org.apache.tapestry5.commons.util.CollectionFactory
+org.apache.tapestry5.internal.util.DelegatingSymbolProvider=org.apache.tapestry5.http.internal.util.DelegatingSymbolProvider
+org.apache.tapestry5.ioc.services.ClassPropertyAdapter=org.apache.tapestry5.commons.services.ClassPropertyAdapter
+org.apache.tapestry5.internal.services.RequestGlobalsImpl=org.apache.tapestry5.http.internal.services.RequestGlobalsImpl
+org.apache.tapestry5.internal.services.ContextImpl=org.apache.tapestry5.http.internal.services.ContextImpl
+org.apache.tapestry5.services.InvalidationEventHub=org.apache.tapestry5.commons.services.InvalidationEventHub
+org.apache.tapestry5.internal.AbstractContributionDef=org.apache.tapestry5.http.internal.AbstractContributionDef
+org.apache.tapestry5.internal.hibernate.EntityApplicationStatePersistenceStrategy=org.apache.tapestry5.hibernate.web.internal.EntityApplicationStatePersistenceStrategy
+org.apache.tapestry5.internal.TapestryAppInitializer=org.apache.tapestry5.http.internal.TapestryAppInitializer
+org.apache.tapestry5.internal.SingleKeySymbolProvider=org.apache.tapestry5.http.internal.SingleKeySymbolProvider
+org.apache.tapestry5.internal.hibernate.PackageNameHibernateConfigurer=org.apache.tapestry5.hibernate.internal.PackageNameHibernateConfigurer
+org.apache.tapestry5.internal.services.ClusteredSessionImpl=org.apache.tapestry5.http.internal.services.ClusteredSessionImpl
+org.apache.tapestry5.ioc.internal.services.StringLocation=org.apache.tapestry5.commons.internal.services.StringLocation
+org.apache.tapestry5.internal.services.SessionLock=org.apache.tapestry5.http.internal.services.SessionLock
+org.apache.tapestry5.internal.services.AnnotationDataTypeAnalyzer=org.apache.tapestry5.commons.internal.services.AnnotationDataTypeAnalyzer
+org.apache.tapestry5.services.UpdateListenerHub=org.apache.tapestry5.ioc.services.UpdateListenerHub
+org.apache.tapestry5.ioc.internal.services.TypeCoercerImpl=org.apache.tapestry5.commons.internal.services.TypeCoercerImpl
+org.apache.tapestry5.internal.hibernate.EntityPersistentFieldStrategy=org.apache.tapestry5.hibernate.web.internal.EntityPersistentFieldStrategy
+org.apache.tapestry5.ioc.Locatable=org.apache.tapestry5.commons.Locatable
+org.apache.tapestry5.ioc.ObjectCreator=org.apache.tapestry5.commons.ObjectCreator
+org.apache.tapestry5.ioc.util.AvailableValues=org.apache.tapestry5.commons.util.AvailableValues
+org.apache.tapestry5.ioc.internal.services.AccessableObjectAnnotationProvider=org.apache.tapestry5.commons.internal.services.AccessableObjectAnnotationProvider
+org.apache.tapestry5.internal.SyntheticModuleDef=org.apache.tapestry5.http.internal.SyntheticModuleDef
+org.apache.tapestry5.internal.services.GenericsResolverImpl=org.apache.tapestry5.commons.internal.services.GenericsResolverImpl
+org.apache.tapestry5.ioc.services.TypeCoercer=org.apache.tapestry5.commons.services.TypeCoercer
+org.apache.tapestry5.internal.services.BaseURLSourceImpl=org.apache.tapestry5.http.internal.services.BaseURLSourceImpl
+org.apache.tapestry5.ioc.internal.util.InheritanceSearch=org.apache.tapestry5.commons.internal.util.InheritanceSearch
+org.apache.tapestry5.ioc.internal.util.TapestryException=org.apache.tapestry5.commons.internal.util.TapestryException
+org.apache.tapestry5.internal.services.ApplicationGlobalsImpl=org.apache.tapestry5.http.internal.services.ApplicationGlobalsImpl
+org.apache.tapestry5.ioc.util.UnknownValueException=org.apache.tapestry5.commons.util.UnknownValueException
+org.apache.tapestry5.OptimizedSessionPersistedObject=org.apache.tapestry5.http.OptimizedSessionPersistedObject
+org.apache.tapestry5.services.DataTypeAnalyzer=org.apache.tapestry5.commons.services.DataTypeAnalyzer
+org.apache.tapestry5.ioc.util.TimeInterval=org.apache.tapestry5.commons.util.TimeInterval
+org.apache.tapestry5.corelib.pages.HibernateStatistics=org.apache.tapestry5.hibernate.web.pages.HibernateStatistics
+org.apache.tapestry5.ioc.util.AbstractMessages=org.apache.tapestry5.commons.util.AbstractMessages
+org.apache.tapestry5.services.ApplicationInitializerFilter=org.apache.tapestry5.http.services.ApplicationInitializerFilter
+org.apache.tapestry5.internal.services.DefaultDataTypeAnalyzer=org.apache.tapestry5.commons.internal.services.DefaultDataTypeAnalyzer
+org.apache.tapestry5.services.HttpServletRequestFilter=org.apache.tapestry5.http.services.HttpServletRequestFilter
+org.apache.tapestry5.ioc.util.CaseInsensitiveMap=org.apache.tapestry5.commons.util.CaseInsensitiveMap
+org.apache.tapestry5.ioc.services.PlasticProxyFactory=org.apache.tapestry5.commons.services.PlasticProxyFactory
+org.apache.tapestry5.services.SessionPersistedObjectAnalyzer=org.apache.tapestry5.http.services.SessionPersistedObjectAnalyzer
+org.apache.tapestry5.services.BaseURLSource=org.apache.tapestry5.http.services.BaseURLSource
+org.apache.tapestry5.services.ApplicationInitializer=org.apache.tapestry5.http.services.ApplicationInitializer
+org.apache.tapestry5.services.ServletApplicationInitializer=org.apache.tapestry5.http.services.ServletApplicationInitializer
+org.apache.tapestry5.internal.gzip.GZipFilter=org.apache.tapestry5.http.internal.gzip.GZipFilter
+org.apache.tapestry5.internal.services.TapestrySessionFactoryImpl=org.apache.tapestry5.http.internal.services.TapestrySessionFactoryImpl
+org.apache.tapestry5.ioc.util.Stack=org.apache.tapestry5.commons.util.Stack
+org.apache.tapestry5.ioc.Location=org.apache.tapestry5.commons.Location
+com.yahoo.platform.yui.compressor.CssCompressor=org.apache.tapestry5.internal.webresources.CssCompressor
+org.apache.tapestry5.ioc.services.CoercionTuple=org.apache.tapestry5.commons.services.CoercionTuple
+org.apache.tapestry5.services.UpdateListener=org.apache.tapestry5.ioc.services.UpdateListener
+org.apache.tapestry5.ioc.ObjectLocator=org.apache.tapestry5.commons.ObjectLocator
+org.apache.tapestry5.ioc.internal.NullAnnotationProvider=org.apache.tapestry5.commons.internal.NullAnnotationProvider
+org.apache.tapestry5.annotations.ImmutableSessionPersistedObject=org.apache.tapestry5.http.annotations.ImmutableSessionPersistedObject
+org.apache.tapestry5.internal.hibernate.CommitAfterWorker=org.apache.tapestry5.hibernate.web.internal.CommitAfterWorker
+org.apache.tapestry5.services.ResponseCompressionAnalyzer=org.apache.tapestry5.http.services.ResponseCompressionAnalyzer
+org.apache.tapestry5.services.assets.CompressionAnalyzer=org.apache.tapestry5.http.services.CompressionAnalyzer
+org.apache.tapestry5.internal.hibernate.HibernateTransactionDecoratorImpl=org.apache.tapestry5.hibernate.internal.HibernateTransactionDecoratorImpl
+org.apache.tapestry5.util.StringToEnumCoercion=org.apache.tapestry5.commons.util.StringToEnumCoercion
+org.apache.tapestry5.internal.services.DefaultSessionPersistedObjectAnalyzer=org.apache.tapestry5.http.internal.services.DefaultSessionPersistedObjectAnalyzer
+org.apache.tapestry5.internal.services.StringInterner=org.apache.tapestry5.commons.internal.services.StringInterner
+org.apache.tapestry5.internal.gzip.BufferedGZipOutputStream=org.apache.tapestry5.http.internal.gzip.BufferedGZipOutputStream
+org.apache.tapestry5.services.InvalidationListener=org.apache.tapestry5.commons.services.InvalidationListener
+org.apache.tapestry5.ioc.internal.util.MessageFormatterImpl=org.apache.tapestry5.commons.internal.util.MessageFormatterImpl
+org.apache.tapestry5.ioc.internal.util.GenericsUtils=org.apache.tapestry5.commons.internal.util.GenericsUtils
+org.apache.tapestry5.hibernate.HibernateGridDataSource=org.apache.tapestry5.hibernate.web.HibernateGridDataSource
+org.apache.tapestry5.internal.gzip.GZIPEnabledResponse=org.apache.tapestry5.http.internal.gzip.GZIPEnabledResponse
+org.apache.tapestry5.ioc.internal.util.LockSupport=org.apache.tapestry5.commons.internal.util.LockSupport
+org.apache.tapestry5.ioc.Resource=org.apache.tapestry5.commons.Resource
diff --git a/tapestry-version-migrator/src/main/resources/org/apache/tapestry5/versionmigrator/change-report-5.7.0.html b/tapestry-version-migrator/src/main/resources/org/apache/tapestry5/versionmigrator/change-report-5.7.0.html
new file mode 100644
index 0000000..6eb1a58
--- /dev/null
+++ b/tapestry-version-migrator/src/main/resources/org/apache/tapestry5/versionmigrator/change-report-5.7.0.html
@@ -0,0 +1 @@
+<html> <head> <title>Changes introduced in Apache Tapestry 5.7.0</title> </head> <body> <table> <thead> <th>Old class name</th> <th>Renamed or moved?</th> <th>New package location</th> <th>Moved artifacts?</th> <th>Old artifact location</th> <th>New artifact location</th> </thead> <tbody> <tr> <td>AbstractMessages</td> <td>yes</td> <td>org.apache.tapestry5.commons.util</td> <td>no</td> <td></td> <td></td> </tr> <tr> <td>Advi [...]
\ No newline at end of file
diff --git a/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/ClassRefactorTest.java b/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/ClassRefactorTest.java
new file mode 100644
index 0000000..f1bef36
--- /dev/null
+++ b/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/ClassRefactorTest.java
@@ -0,0 +1,112 @@
+// 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.apache.tapestry5.versionmigrator;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test class for {@link ClassRefactor}.
+ */
+@Test(groups = "unit")
+public class ClassRefactorTest
+{
+ final private static String VALID = "valid";
+ final private static String SIMPLE_CLASS_NAME = "Something";
+ final private static String PACKAGE_NAME = "org.apache.tapestry5";
+ final private static String CLASS_NAME = PACKAGE_NAME + "." + SIMPLE_CLASS_NAME;
+ final private static String ARTIFACT_NAME = "tapestry-subproject";
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void constructor_first_parameter_check()
+ {
+ new ClassRefactor(null, VALID, VALID, VALID);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void constructor_second_parameter_check()
+ {
+ new ClassRefactor(VALID, null, VALID, VALID);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void constructor_third_parameter_check()
+ {
+ new ClassRefactor(VALID, VALID, null, VALID);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void constructor_fourth_parameter_check()
+ {
+ new ClassRefactor(VALID, VALID, VALID, null);
+ }
+
+ @Test
+ public void is_moved_between_artifacts()
+ {
+
+ Assert.assertTrue(
+ new ClassRefactor(
+ CLASS_NAME, CLASS_NAME,
+ ARTIFACT_NAME, ARTIFACT_NAME + "blah").isMovedBetweenArtifacts(),
+ "Artifact changed");
+
+ Assert.assertFalse(
+ new ClassRefactor(
+ CLASS_NAME, CLASS_NAME + "Blah",
+ ARTIFACT_NAME, ARTIFACT_NAME).isMovedBetweenArtifacts(),
+ "Artifact not changed");
+
+ }
+
+ @Test
+ public void is_renamed()
+ {
+
+ Assert.assertTrue(
+ new ClassRefactor(
+ CLASS_NAME, CLASS_NAME + "Blah",
+ ARTIFACT_NAME, ARTIFACT_NAME).isRenamed(),
+ "Fully qualified class name changed");
+
+ Assert.assertFalse(
+ new ClassRefactor(
+ CLASS_NAME, CLASS_NAME,
+ ARTIFACT_NAME, ARTIFACT_NAME + "blah").isRenamed(),
+ "Fully qualified class name changed");
+ }
+
+ @Test
+ public void get_simple_old_class_name()
+ {
+
+ Assert.assertEquals(
+ new ClassRefactor(
+ CLASS_NAME, CLASS_NAME,
+ ARTIFACT_NAME, ARTIFACT_NAME).getSimpleOldClassName(),
+ SIMPLE_CLASS_NAME,
+ "Wrong simple old class name.");
+ }
+
+ @Test
+ public void get_new_package_name()
+ {
+
+ Assert.assertEquals(
+ new ClassRefactor(
+ CLASS_NAME, CLASS_NAME.replace("org.", "com."),
+ ARTIFACT_NAME, ARTIFACT_NAME).getNewPackageName(),
+ PACKAGE_NAME,
+ "Wrong new package name.");
+ }
+
+}
diff --git a/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/ArtifactChangeRefactorCommitParserTest.java b/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/ArtifactChangeRefactorCommitParserTest.java
new file mode 100644
index 0000000..f4cf979
--- /dev/null
+++ b/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/ArtifactChangeRefactorCommitParserTest.java
@@ -0,0 +1,41 @@
+// 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.apache.tapestry5.versionmigrator.internal;
+
+import java.util.Optional;
+
+import org.apache.tapestry5.versionmigrator.ClassRefactor;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test class for {@link ArtifactChangeRefactorCommitParser}.
+ */
+@Test(groups = "unit")
+public class ArtifactChangeRefactorCommitParserTest
+{
+ @Test
+ public void valid_line()
+ {
+ // {tapestry-ioc => tapestry5-annotations}/src/main/java/org/apache/tapestry5/ioc/annotations/Advise.java
+ ArtifactChangeRefactorCommitParser parser = new ArtifactChangeRefactorCommitParser();
+ Optional<ClassRefactor> optionalRefactor = parser.apply(ArtifactChangeRefactorCommitParser.EXAMPLE);
+ Assert.assertTrue(optionalRefactor.isPresent(), "Line not detected as a change of artifact.");
+ ClassRefactor refactor = optionalRefactor.get();
+ final String expectedClassName = "org.apache.tapestry5.ioc.annotations.Advise";
+ Assert.assertEquals(refactor.getNewClassName(), expectedClassName);
+ Assert.assertEquals(refactor.getOldClassName(), expectedClassName);
+ Assert.assertEquals(refactor.getDestinationArtifact(), "tapestry5-annotations");
+ Assert.assertEquals(refactor.getSourceArtifact(), "tapestry-ioc");
+ }
+
+}
diff --git a/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/PackageAndArtifactChangeRefactorCommitParserTest.java b/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/PackageAndArtifactChangeRefactorCommitParserTest.java
new file mode 100644
index 0000000..fab4063
--- /dev/null
+++ b/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/PackageAndArtifactChangeRefactorCommitParserTest.java
@@ -0,0 +1,40 @@
+// 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.apache.tapestry5.versionmigrator.internal;
+
+import java.util.Optional;
+
+import org.apache.tapestry5.versionmigrator.ClassRefactor;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test class for {@link PackageAndArtifactChangeRefactorCommitParser}.
+ */
+@Test(groups = "unit")
+public class PackageAndArtifactChangeRefactorCommitParserTest
+{
+ @Test
+ public void valid_line()
+ {
+ // {tapestry-ioc/src/main/java/org/apache/tapestry5/ioc => commons/src/main/java/org/apache/tapestry5/commons}/ObjectProvider.java
+ PackageAndArtifactChangeRefactorCommitParser parser = new PackageAndArtifactChangeRefactorCommitParser();
+ Optional<ClassRefactor> optionalRefactor = parser.apply(PackageAndArtifactChangeRefactorCommitParser.EXAMPLE);
+ Assert.assertTrue(optionalRefactor.isPresent(), "Line not detected as a change of package and artifact.");
+ ClassRefactor refactor = optionalRefactor.get();
+ Assert.assertEquals(refactor.getNewClassName(), "org.apache.tapestry5.commons.ObjectProvider");
+ Assert.assertEquals(refactor.getOldClassName(), "org.apache.tapestry5.commons.ObjectProvider");
+ Assert.assertEquals(refactor.getDestinationArtifact(), "commons");
+ Assert.assertEquals(refactor.getSourceArtifact(), "tapestry-ioc");
+ }
+
+}
diff --git a/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/PackageChangeRefactorCommitParserTest.java b/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/PackageChangeRefactorCommitParserTest.java
new file mode 100644
index 0000000..09d2402
--- /dev/null
+++ b/tapestry-version-migrator/src/test/java/org/apache/tapestry5/versionmigrator/internal/PackageChangeRefactorCommitParserTest.java
@@ -0,0 +1,40 @@
+// 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.apache.tapestry5.versionmigrator.internal;
+
+import java.util.Optional;
+
+import org.apache.tapestry5.versionmigrator.ClassRefactor;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test class for {@link PackageChangeRefactorCommitParser}.
+ */
+@Test(groups = "unit")
+public class PackageChangeRefactorCommitParserTest
+{
+ @Test
+ public void valid_line()
+ {
+ // commons/src/main/java/org/apache/tapestry5/{ioc => commons}/Messages.java (98%)
+ PackageChangeRefactorCommitParser parser = new PackageChangeRefactorCommitParser();
+ Optional<ClassRefactor> optionalRefactor = parser.apply(PackageChangeRefactorCommitParser.EXAMPLE);
+ Assert.assertTrue(optionalRefactor.isPresent(), "Line not detected as a change of package.");
+ ClassRefactor refactor = optionalRefactor.get();
+ Assert.assertEquals(refactor.getNewClassName(), "org.apache.tapestry5.commons.Messages");
+ Assert.assertEquals(refactor.getOldClassName(), "org.apache.tapestry5.commons.Messages");
+ Assert.assertEquals(refactor.getDestinationArtifact(), "commons");
+ Assert.assertEquals(refactor.getSourceArtifact(), "commons");
+ }
+
+}
diff --git a/tapestry-version-migrator/test-sources/ClassAtRootFolder.java b/tapestry-version-migrator/test-sources/ClassAtRootFolder.java
new file mode 100644
index 0000000..e2e153f
--- /dev/null
+++ b/tapestry-version-migrator/test-sources/ClassAtRootFolder.java
@@ -0,0 +1,11 @@
+import org.apache.tapestry5.Link;
+
+public class ClassAtRootFolder {
+
+ org.apache.tapestry5.ioc.internal.services.CompoundCoercion field;
+
+ public void blah() {
+
+ }
+
+}
diff --git a/tapestry-version-migrator/test-sources/subfolder/subsubfolder/ClassAtSubFolder.java b/tapestry-version-migrator/test-sources/subfolder/subsubfolder/ClassAtSubFolder.java
new file mode 100644
index 0000000..4ed4682
--- /dev/null
+++ b/tapestry-version-migrator/test-sources/subfolder/subsubfolder/ClassAtSubFolder.java
@@ -0,0 +1,15 @@
+import org.apache.tapestry5.Link;
+
+import org.apache.tapestry5.ioc.services.Coercion;
+import org.apache.tapestry5.ContentType;
+
+public class ClassAtSubSubFolder {
+
+ org.apache.tapestry5.ContentType contentType;
+ org.apache.tapestry5.ioc.internal.services.CompoundCoercion field;
+
+ public void blah() {
+
+ }
+
+}