summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/command
diff options
context:
space:
mode:
authorGravatar Runemoro2020-06-03 13:39:42 -0400
committerGravatar GitHub2020-06-03 18:39:42 +0100
commit0f47403d0220757fed189b76e2071e25b1025cb8 (patch)
tree879bf72c4476f0a5e0d82da99d7ff2b2276bcaca /src/main/java/cuchaz/enigma/command
parentFix search dialog hanging for a short time sometimes (#250) (diff)
downloadenigma-fork-0f47403d0220757fed189b76e2071e25b1025cb8.tar.gz
enigma-fork-0f47403d0220757fed189b76e2071e25b1025cb8.tar.xz
enigma-fork-0f47403d0220757fed189b76e2071e25b1025cb8.zip
Split GUI code to separate module (#242)
* Split into modules * Post merge compile fixes Co-authored-by: modmuss50 <modmuss50@gmail.com>
Diffstat (limited to 'src/main/java/cuchaz/enigma/command')
-rw-r--r--src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java77
-rw-r--r--src/main/java/cuchaz/enigma/command/Command.java154
-rw-r--r--src/main/java/cuchaz/enigma/command/ComposeMappingsCommand.java41
-rw-r--r--src/main/java/cuchaz/enigma/command/ConvertMappingsCommand.java39
-rw-r--r--src/main/java/cuchaz/enigma/command/DecompileCommand.java54
-rw-r--r--src/main/java/cuchaz/enigma/command/DeobfuscateCommand.java37
-rw-r--r--src/main/java/cuchaz/enigma/command/InvertMappingsCommand.java40
-rw-r--r--src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java69
-rw-r--r--src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java148
9 files changed, 0 insertions, 659 deletions
diff --git a/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java b/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java
deleted file mode 100644
index 9d238e3..0000000
--- a/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java
+++ /dev/null
@@ -1,77 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.Enigma;
4import cuchaz.enigma.EnigmaProject;
5import cuchaz.enigma.ProgressListener;
6import cuchaz.enigma.analysis.index.JarIndex;
7import cuchaz.enigma.translation.mapping.EntryMapping;
8import cuchaz.enigma.translation.mapping.MappingSaveParameters;
9import cuchaz.enigma.translation.mapping.serde.MappingFormat;
10import cuchaz.enigma.translation.mapping.tree.EntryTree;
11import cuchaz.enigma.translation.representation.entry.ClassEntry;
12
13import java.nio.file.Path;
14import java.util.Set;
15import java.util.stream.Collectors;
16
17public class CheckMappingsCommand extends Command {
18
19 public CheckMappingsCommand() {
20 super("checkmappings");
21 }
22
23 @Override
24 public String getUsage() {
25 return "<in jar> <mappings file>";
26 }
27
28 @Override
29 public boolean isValidArgument(int length) {
30 return length == 2;
31 }
32
33 @Override
34 public void run(String... args) throws Exception {
35 Path fileJarIn = getReadableFile(getArg(args, 0, "in jar", true)).toPath();
36 Path fileMappings = getReadablePath(getArg(args, 1, "mappings file", true));
37
38 Enigma enigma = Enigma.create();
39
40 System.out.println("Reading JAR...");
41
42 EnigmaProject project = enigma.openJar(fileJarIn, ProgressListener.none());
43
44 System.out.println("Reading mappings...");
45
46 MappingFormat format = chooseEnigmaFormat(fileMappings);
47 MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters();
48
49 EntryTree<EntryMapping> mappings = format.read(fileMappings, ProgressListener.none(), saveParameters);
50 project.setMappings(mappings);
51
52 JarIndex idx = project.getJarIndex();
53
54 boolean error = false;
55
56 for (Set<ClassEntry> partition : idx.getPackageVisibilityIndex().getPartitions()) {
57 long packages = partition.stream()
58 .map(project.getMapper()::deobfuscate)
59 .map(ClassEntry::getPackageName)
60 .distinct()
61 .count();
62 if (packages > 1) {
63 error = true;
64 System.err.println("ERROR: Must be in one package:\n" + partition.stream()
65 .map(project.getMapper()::deobfuscate)
66 .map(ClassEntry::toString)
67 .sorted()
68 .collect(Collectors.joining("\n"))
69 );
70 }
71 }
72
73 if (error) {
74 throw new IllegalStateException("Errors in package visibility detected, see SysErr above");
75 }
76 }
77}
diff --git a/src/main/java/cuchaz/enigma/command/Command.java b/src/main/java/cuchaz/enigma/command/Command.java
deleted file mode 100644
index 09dd321..0000000
--- a/src/main/java/cuchaz/enigma/command/Command.java
+++ /dev/null
@@ -1,154 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.Enigma;
4import cuchaz.enigma.EnigmaProject;
5import cuchaz.enigma.ProgressListener;
6import cuchaz.enigma.translation.mapping.EntryMapping;
7import cuchaz.enigma.translation.mapping.MappingSaveParameters;
8import cuchaz.enigma.translation.mapping.serde.MappingFormat;
9import cuchaz.enigma.translation.mapping.tree.EntryTree;
10
11import java.io.File;
12import java.nio.file.Files;
13import java.nio.file.Path;
14import java.nio.file.Paths;
15
16import com.google.common.io.MoreFiles;
17
18public abstract class Command {
19 public final String name;
20
21 protected Command(String name) {
22 this.name = name;
23 }
24
25 public abstract String getUsage();
26
27 public abstract boolean isValidArgument(int length);
28
29 public abstract void run(String... args) throws Exception;
30
31 protected static EnigmaProject openProject(Path fileJarIn, Path fileMappings) throws Exception {
32 ProgressListener progress = new ConsoleProgressListener();
33
34 Enigma enigma = Enigma.create();
35
36 System.out.println("Reading jar...");
37 EnigmaProject project = enigma.openJar(fileJarIn, progress);
38
39 if (fileMappings != null) {
40 System.out.println("Reading mappings...");
41
42 MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters();
43 EntryTree<EntryMapping> mappings = chooseEnigmaFormat(fileMappings).read(fileMappings, progress, saveParameters);
44
45 project.setMappings(mappings);
46 }
47
48 return project;
49 }
50
51 protected static MappingFormat chooseEnigmaFormat(Path path) {
52 if (Files.isDirectory(path)) {
53 return MappingFormat.ENIGMA_DIRECTORY;
54 } else if ("zip".equalsIgnoreCase(MoreFiles.getFileExtension(path))) {
55 return MappingFormat.ENIGMA_ZIP;
56 } else {
57 return MappingFormat.ENIGMA_FILE;
58 }
59 }
60
61 protected static File getWritableFile(String path) {
62 if (path == null) {
63 return null;
64 }
65 File file = new File(path).getAbsoluteFile();
66 File dir = file.getParentFile();
67 if (dir == null) {
68 throw new IllegalArgumentException("Cannot write file: " + path);
69 }
70 // quick fix to avoid stupid stuff in Gradle code
71 if (!dir.isDirectory()) {
72 dir.mkdirs();
73 }
74 return file;
75 }
76
77 protected static File getWritableFolder(String path) {
78 if (path == null) {
79 return null;
80 }
81 File dir = new File(path).getAbsoluteFile();
82 if (!dir.exists()) {
83 throw new IllegalArgumentException("Cannot write to folder: " + dir);
84 }
85 return dir;
86 }
87
88 protected static File getReadableFile(String path) {
89 if (path == null) {
90 return null;
91 }
92 File file = new File(path).getAbsoluteFile();
93 if (!file.exists()) {
94 throw new IllegalArgumentException("Cannot find file: " + file.getAbsolutePath());
95 }
96 return file;
97 }
98
99 protected static Path getReadablePath(String path) {
100 if (path == null) {
101 return null;
102 }
103 Path file = Paths.get(path).toAbsolutePath();
104 if (!Files.exists(file)) {
105 throw new IllegalArgumentException("Cannot find file: " + file.toString());
106 }
107 return file;
108 }
109
110 protected static String getArg(String[] args, int i, String name, boolean required) {
111 if (i >= args.length) {
112 if (required) {
113 throw new IllegalArgumentException(name + " is required");
114 } else {
115 return null;
116 }
117 }
118 return args[i];
119 }
120
121 public static class ConsoleProgressListener implements ProgressListener {
122
123 private static final int ReportTime = 5000; // 5s
124
125 private int totalWork;
126 private long startTime;
127 private long lastReportTime;
128
129 @Override
130 public void init(int totalWork, String title) {
131 this.totalWork = totalWork;
132 this.startTime = System.currentTimeMillis();
133 this.lastReportTime = this.startTime;
134 System.out.println(title);
135 }
136
137 @Override
138 public void step(int numDone, String message) {
139 long now = System.currentTimeMillis();
140 boolean isLastUpdate = numDone == this.totalWork;
141 boolean shouldReport = isLastUpdate || now - this.lastReportTime > ReportTime;
142
143 if (shouldReport) {
144 int percent = numDone * 100 / this.totalWork;
145 System.out.println(String.format("\tProgress: %3d%%", percent));
146 this.lastReportTime = now;
147 }
148 if (isLastUpdate) {
149 double elapsedSeconds = (now - this.startTime) / 1000.0;
150 System.out.println(String.format("Finished in %.1f seconds", elapsedSeconds));
151 }
152 }
153 }
154}
diff --git a/src/main/java/cuchaz/enigma/command/ComposeMappingsCommand.java b/src/main/java/cuchaz/enigma/command/ComposeMappingsCommand.java
deleted file mode 100644
index f57f1fa..0000000
--- a/src/main/java/cuchaz/enigma/command/ComposeMappingsCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.throwables.MappingParseException;
4import cuchaz.enigma.translation.mapping.EntryMapping;
5import cuchaz.enigma.translation.mapping.MappingFileNameFormat;
6import cuchaz.enigma.translation.mapping.MappingSaveParameters;
7import cuchaz.enigma.translation.mapping.tree.EntryTree;
8import cuchaz.enigma.utils.Utils;
9
10import java.io.IOException;
11import java.nio.file.Path;
12import java.nio.file.Paths;
13
14public class ComposeMappingsCommand extends Command {
15 public ComposeMappingsCommand() {
16 super("compose-mappings");
17 }
18
19 @Override
20 public String getUsage() {
21 return "<left-format> <left> <right-format> <right> <result-format> <result> <keep-mode>";
22 }
23
24 @Override
25 public boolean isValidArgument(int length) {
26 return length == 7;
27 }
28
29 @Override
30 public void run(String... args) throws IOException, MappingParseException {
31 MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF);
32
33 EntryTree<EntryMapping> left = MappingCommandsUtil.read(args[0], Paths.get(args[1]), saveParameters);
34 EntryTree<EntryMapping> right = MappingCommandsUtil.read(args[2], Paths.get(args[3]), saveParameters);
35 EntryTree<EntryMapping> result = MappingCommandsUtil.compose(left, right, args[6].equals("left") || args[6].equals("both"), args[6].equals("right") || args[6].equals("both"));
36
37 Path output = Paths.get(args[5]);
38 Utils.delete(output);
39 MappingCommandsUtil.write(result, args[4], output, saveParameters);
40 }
41}
diff --git a/src/main/java/cuchaz/enigma/command/ConvertMappingsCommand.java b/src/main/java/cuchaz/enigma/command/ConvertMappingsCommand.java
deleted file mode 100644
index 689df02..0000000
--- a/src/main/java/cuchaz/enigma/command/ConvertMappingsCommand.java
+++ /dev/null
@@ -1,39 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.throwables.MappingParseException;
4import cuchaz.enigma.translation.mapping.EntryMapping;
5import cuchaz.enigma.translation.mapping.MappingFileNameFormat;
6import cuchaz.enigma.translation.mapping.MappingSaveParameters;
7import cuchaz.enigma.translation.mapping.tree.EntryTree;
8import cuchaz.enigma.utils.Utils;
9
10import java.io.IOException;
11import java.nio.file.Path;
12import java.nio.file.Paths;
13
14public class ConvertMappingsCommand extends Command {
15 public ConvertMappingsCommand() {
16 super("convert-mappings");
17 }
18
19 @Override
20 public String getUsage() {
21 return "<source-format> <source> <result-format> <result>";
22 }
23
24 @Override
25 public boolean isValidArgument(int length) {
26 return length == 4;
27 }
28
29 @Override
30 public void run(String... args) throws IOException, MappingParseException {
31 MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF);
32
33 EntryTree<EntryMapping> mappings = MappingCommandsUtil.read(args[0], Paths.get(args[1]), saveParameters);
34
35 Path output = Paths.get(args[3]);
36 Utils.delete(output);
37 MappingCommandsUtil.write(mappings, args[2], output, saveParameters);
38 }
39}
diff --git a/src/main/java/cuchaz/enigma/command/DecompileCommand.java b/src/main/java/cuchaz/enigma/command/DecompileCommand.java
deleted file mode 100644
index 3d15dac..0000000
--- a/src/main/java/cuchaz/enigma/command/DecompileCommand.java
+++ /dev/null
@@ -1,54 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.EnigmaProject;
4import cuchaz.enigma.ProgressListener;
5import cuchaz.enigma.source.DecompilerService;
6import cuchaz.enigma.source.Decompilers;
7
8import java.lang.reflect.Field;
9import java.nio.file.Path;
10import java.util.Locale;
11
12public class DecompileCommand extends Command {
13
14 public DecompileCommand() {
15 super("decompile");
16 }
17
18 @Override
19 public String getUsage() {
20 return "<decompiler> <in jar> <out folder> [<mappings file>]";
21 }
22
23 @Override
24 public boolean isValidArgument(int length) {
25 return length == 2 || length == 3;
26 }
27
28 @Override
29 public void run(String... args) throws Exception {
30 String decompilerName = getArg(args, 1, "decompiler", true);
31 Path fileJarIn = getReadableFile(getArg(args, 1, "in jar", true)).toPath();
32 Path fileJarOut = getWritableFolder(getArg(args, 2, "out folder", true)).toPath();
33 Path fileMappings = getReadablePath(getArg(args, 3, "mappings file", false));
34
35 DecompilerService decompilerService;
36
37 try {
38 Field decompilerField = Decompilers.class.getField(decompilerName.toUpperCase(Locale.ROOT));
39 decompilerService = (DecompilerService) decompilerField.get(null);
40 } catch (NoSuchFieldException e) {
41 System.err.println("Decompiler not found.");
42 return;
43 }
44
45 EnigmaProject project = openProject(fileJarIn, fileMappings);
46
47 ProgressListener progress = new ConsoleProgressListener();
48
49 EnigmaProject.JarExport jar = project.exportRemappedJar(progress);
50 EnigmaProject.SourceExport source = jar.decompile(progress, decompilerService);
51
52 source.write(fileJarOut, progress);
53 }
54}
diff --git a/src/main/java/cuchaz/enigma/command/DeobfuscateCommand.java b/src/main/java/cuchaz/enigma/command/DeobfuscateCommand.java
deleted file mode 100644
index b0d2a7d..0000000
--- a/src/main/java/cuchaz/enigma/command/DeobfuscateCommand.java
+++ /dev/null
@@ -1,37 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.EnigmaProject;
4import cuchaz.enigma.ProgressListener;
5
6import java.nio.file.Path;
7
8public class DeobfuscateCommand extends Command {
9
10 public DeobfuscateCommand() {
11 super("deobfuscate");
12 }
13
14 @Override
15 public String getUsage() {
16 return "<in jar> <out jar> [<mappings file>]";
17 }
18
19 @Override
20 public boolean isValidArgument(int length) {
21 return length == 2 || length == 3;
22 }
23
24 @Override
25 public void run(String... args) throws Exception {
26 Path fileJarIn = getReadablePath(getArg(args, 0, "in jar", true));
27 Path fileJarOut = getWritableFile(getArg(args, 1, "out jar", true)).toPath();
28 Path fileMappings = getReadablePath(getArg(args, 2, "mappings file", false));
29
30 EnigmaProject project = openProject(fileJarIn, fileMappings);
31
32 ProgressListener progress = new ConsoleProgressListener();
33
34 EnigmaProject.JarExport jar = project.exportRemappedJar(progress);
35 jar.write(fileJarOut, progress);
36 }
37}
diff --git a/src/main/java/cuchaz/enigma/command/InvertMappingsCommand.java b/src/main/java/cuchaz/enigma/command/InvertMappingsCommand.java
deleted file mode 100644
index cd11e2e..0000000
--- a/src/main/java/cuchaz/enigma/command/InvertMappingsCommand.java
+++ /dev/null
@@ -1,40 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.throwables.MappingParseException;
4import cuchaz.enigma.translation.mapping.EntryMapping;
5import cuchaz.enigma.translation.mapping.MappingFileNameFormat;
6import cuchaz.enigma.translation.mapping.MappingSaveParameters;
7import cuchaz.enigma.translation.mapping.tree.EntryTree;
8import cuchaz.enigma.utils.Utils;
9
10import java.io.IOException;
11import java.nio.file.Path;
12import java.nio.file.Paths;
13
14public class InvertMappingsCommand extends Command {
15 public InvertMappingsCommand() {
16 super("invert-mappings");
17 }
18
19 @Override
20 public String getUsage() {
21 return "<source-format> <source> <result-format> <result>";
22 }
23
24 @Override
25 public boolean isValidArgument(int length) {
26 return length == 4;
27 }
28
29 @Override
30 public void run(String... args) throws IOException, MappingParseException {
31 MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF);
32
33 EntryTree<EntryMapping> source = MappingCommandsUtil.read(args[0], Paths.get(args[1]), saveParameters);
34 EntryTree<EntryMapping> result = MappingCommandsUtil.invert(source);
35
36 Path output = Paths.get(args[3]);
37 Utils.delete(output);
38 MappingCommandsUtil.write(result, args[2], output, saveParameters);
39 }
40}
diff --git a/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java b/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java
deleted file mode 100644
index eb8d5dc..0000000
--- a/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java
+++ /dev/null
@@ -1,69 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.ProgressListener;
4import cuchaz.enigma.analysis.ClassCache;
5import cuchaz.enigma.analysis.index.BridgeMethodIndex;
6import cuchaz.enigma.analysis.index.JarIndex;
7import cuchaz.enigma.throwables.MappingParseException;
8import cuchaz.enigma.translation.MappingTranslator;
9import cuchaz.enigma.translation.Translator;
10import cuchaz.enigma.translation.mapping.*;
11import cuchaz.enigma.translation.mapping.tree.EntryTree;
12import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
13import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
14import cuchaz.enigma.translation.representation.entry.MethodEntry;
15import cuchaz.enigma.utils.Utils;
16
17import java.io.IOException;
18import java.nio.file.Path;
19import java.nio.file.Paths;
20import java.util.Map;
21
22public class MapSpecializedMethodsCommand extends Command {
23 public MapSpecializedMethodsCommand() {
24 super("map-specialized-methods");
25 }
26
27 @Override
28 public String getUsage() {
29 return "<jar> <source-format> <source> <result-format> <result>";
30 }
31
32 @Override
33 public boolean isValidArgument(int length) {
34 return length == 5;
35 }
36
37 @Override
38 public void run(String... args) throws IOException, MappingParseException {
39 run(Paths.get(args[0]), args[1], Paths.get(args[2]), args[3], Paths.get(args[4]));
40 }
41
42 public static void run(Path jar, String sourceFormat, Path sourcePath, String resultFormat, Path output) throws IOException, MappingParseException {
43 MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF);
44 EntryTree<EntryMapping> source = MappingCommandsUtil.read(sourceFormat, sourcePath, saveParameters);
45 EntryTree<EntryMapping> result = new HashEntryTree<>();
46 ClassCache classCache = ClassCache.of(jar);
47 JarIndex jarIndex = classCache.index(ProgressListener.none());
48 BridgeMethodIndex bridgeMethodIndex = jarIndex.getBridgeMethodIndex();
49 Translator translator = new MappingTranslator(source, jarIndex.getEntryResolver());
50
51 // Copy all non-specialized methods
52 for (EntryTreeNode<EntryMapping> node : source) {
53 if (!(node.getEntry() instanceof MethodEntry) || !bridgeMethodIndex.isSpecializedMethod((MethodEntry) node.getEntry())) {
54 result.insert(node.getEntry(), node.getValue());
55 }
56 }
57
58 // Add correct mappings for specialized methods
59 for (Map.Entry<MethodEntry, MethodEntry> entry : bridgeMethodIndex.getBridgeToSpecialized().entrySet()) {
60 MethodEntry bridge = entry.getKey();
61 MethodEntry specialized = entry.getValue();
62 String name = translator.translate(bridge).getName();
63 result.insert(specialized, new EntryMapping(name));
64 }
65
66 Utils.delete(output);
67 MappingCommandsUtil.write(result, resultFormat, output, saveParameters);
68 }
69}
diff --git a/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java b/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java
deleted file mode 100644
index fc7afbc..0000000
--- a/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java
+++ /dev/null
@@ -1,148 +0,0 @@
1package cuchaz.enigma.command;
2
3import cuchaz.enigma.ProgressListener;
4import cuchaz.enigma.throwables.MappingParseException;
5import cuchaz.enigma.translation.MappingTranslator;
6import cuchaz.enigma.translation.Translator;
7import cuchaz.enigma.translation.mapping.EntryMapping;
8import cuchaz.enigma.translation.mapping.MappingSaveParameters;
9import cuchaz.enigma.translation.mapping.VoidEntryResolver;
10import cuchaz.enigma.translation.mapping.serde.*;
11import cuchaz.enigma.translation.mapping.tree.EntryTree;
12import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
13import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
14import cuchaz.enigma.translation.representation.entry.ClassEntry;
15import cuchaz.enigma.translation.representation.entry.Entry;
16import cuchaz.enigma.translation.representation.entry.FieldEntry;
17import cuchaz.enigma.translation.representation.entry.MethodEntry;
18
19import java.io.IOException;
20import java.nio.file.Files;
21import java.nio.file.Path;
22import java.util.HashSet;
23import java.util.Set;
24
25public final class MappingCommandsUtil {
26 private MappingCommandsUtil() {}
27
28 public static EntryTree<EntryMapping> invert(EntryTree<EntryMapping> mappings) {
29 Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE);
30 EntryTree<EntryMapping> result = new HashEntryTree<>();
31
32 for (EntryTreeNode<EntryMapping> node : mappings) {
33 Entry<?> leftEntry = node.getEntry();
34 EntryMapping leftMapping = node.getValue();
35
36 if (!(leftEntry instanceof ClassEntry || leftEntry instanceof MethodEntry || leftEntry instanceof FieldEntry)) {
37 result.insert(translator.translate(leftEntry), leftMapping);
38 continue;
39 }
40
41 Entry<?> rightEntry = translator.translate(leftEntry);
42
43 result.insert(rightEntry, leftMapping == null ? null : new EntryMapping(leftEntry.getName())); // TODO: leftMapping.withName once javadoc PR is merged
44 }
45
46 return result;
47 }
48
49 public static EntryTree<EntryMapping> compose(EntryTree<EntryMapping> left, EntryTree<EntryMapping> right, boolean keepLeftOnly, boolean keepRightOnly) {
50 Translator leftTranslator = new MappingTranslator(left, VoidEntryResolver.INSTANCE);
51 EntryTree<EntryMapping> result = new HashEntryTree<>();
52 Set<Entry<?>> addedMappings = new HashSet<>();
53
54 for (EntryTreeNode<EntryMapping> node : left) {
55 Entry<?> leftEntry = node.getEntry();
56 EntryMapping leftMapping = node.getValue();
57
58 Entry<?> rightEntry = leftTranslator.translate(leftEntry);
59
60 EntryMapping rightMapping = right.get(rightEntry);
61 if (rightMapping != null) {
62 result.insert(leftEntry, rightMapping);
63 addedMappings.add(rightEntry);
64 } else if (keepLeftOnly) {
65 result.insert(leftEntry, leftMapping);
66 }
67 }
68
69 if (keepRightOnly) {
70 Translator leftInverseTranslator = new MappingTranslator(invert(left), VoidEntryResolver.INSTANCE);
71 for (EntryTreeNode<EntryMapping> node : right) {
72 Entry<?> rightEntry = node.getEntry();
73 EntryMapping rightMapping = node.getValue();
74
75 if (!addedMappings.contains(rightEntry)) {
76 result.insert(leftInverseTranslator.translate(rightEntry), rightMapping);
77 }
78 }
79 }
80 return result;
81 }
82
83 public static EntryTree<EntryMapping> read(String type, Path path, MappingSaveParameters saveParameters) throws MappingParseException, IOException {
84 if (type.equals("enigma")) {
85 return (Files.isDirectory(path) ? EnigmaMappingsReader.DIRECTORY : EnigmaMappingsReader.ZIP).read(path, ProgressListener.none(), saveParameters);
86 }
87
88 if (type.equals("tiny")) {
89 return TinyMappingsReader.INSTANCE.read(path, ProgressListener.none(), saveParameters);
90 }
91
92 MappingFormat format = null;
93 try {
94 format = MappingFormat.valueOf(type.toUpperCase());
95 } catch (IllegalArgumentException ignored) {
96 if (type.equals("tinyv2")) {
97 format = MappingFormat.TINY_V2;
98 }
99 }
100
101 if (format != null) {
102 return format.getReader().read(path, ProgressListener.none(), saveParameters);
103 }
104
105 throw new IllegalArgumentException("no reader for " + type);
106 }
107
108 public static void write(EntryTree<EntryMapping> mappings, String type, Path path, MappingSaveParameters saveParameters) {
109 if (type.equals("enigma")) {
110 EnigmaMappingsWriter.DIRECTORY.write(mappings, path, ProgressListener.none(), saveParameters);
111 return;
112 }
113
114 if (type.startsWith("tinyv2:") || type.startsWith("tiny_v2:")) {
115 String[] split = type.split(":");
116
117 if (split.length != 3) {
118 throw new IllegalArgumentException("specify column names as 'tinyv2:from_namespace:to_namespace'");
119 }
120
121 new TinyV2Writer(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
122 return;
123 }
124
125 if (type.startsWith("tiny:")) {
126 String[] split = type.split(":");
127
128 if (split.length != 3) {
129 throw new IllegalArgumentException("specify column names as 'tiny:from_column:to_column'");
130 }
131
132 new TinyMappingsWriter(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
133 return;
134 }
135
136 MappingFormat format = null;
137 try {
138 format = MappingFormat.valueOf(type.toUpperCase());
139 } catch (IllegalArgumentException ignored) {}
140
141 if (format != null) {
142 format.getWriter().write(mappings, path, ProgressListener.none(), saveParameters);
143 return;
144 }
145
146 throw new IllegalArgumentException("no writer for " + type);
147 }
148}