- 'error' was an old entry but now we have multiple entries under 'error' (which is now a section), so we need to ensure that we migrate the old 'error' entry before the migration sets anything under that path
150 lines
6.3 KiB
Java
150 lines
6.3 KiB
Java
package tools.messages;
|
|
|
|
import ch.jalu.configme.SettingsManager;
|
|
import ch.jalu.configme.configurationdata.ConfigurationData;
|
|
import ch.jalu.configme.properties.Property;
|
|
import ch.jalu.configme.resource.PropertyResource;
|
|
import ch.jalu.configme.resource.YamlFileResource;
|
|
import fr.xephi.authme.message.updater.MessageUpdater;
|
|
import fr.xephi.authme.message.updater.MessageUpdater.MigraterYamlFileResource;
|
|
import org.bukkit.configuration.file.FileConfiguration;
|
|
import tools.utils.FileIoUtils;
|
|
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
/**
|
|
* Writes to a messages file, adding comments with the default file's message where
|
|
* entries are missing.
|
|
* <p>
|
|
* This writer writes to the file twice: once with ConfigMe to ensure a proper order
|
|
* of the properties and comments, and a second time to add any custom comments that
|
|
* were at the top of the file and to separate comments by new lines (which ConfigMe
|
|
* currently doesn't support).
|
|
*/
|
|
public final class MessagesFileWriter {
|
|
|
|
/** Marker used inside a text to signal that it should be a comment later on. */
|
|
private static final String COMMENT_MARKER = "::COMMENT::";
|
|
|
|
private static final Pattern SPACES_BEFORE_TEXT_PATTERN = Pattern.compile("(\\s+)\\w.*");
|
|
|
|
/** The messages file to update. */
|
|
private final File file;
|
|
/** Messages from the default file. */
|
|
private final FileConfiguration defaultFile;
|
|
|
|
private MessagesFileWriter(File file, FileConfiguration defaultFile) {
|
|
this.file = file;
|
|
this.defaultFile = defaultFile;
|
|
}
|
|
|
|
public static void writeToFileWithCommentsFromDefault(File file, FileConfiguration configuration) {
|
|
new MessagesFileWriter(file, configuration).performWrite();
|
|
}
|
|
|
|
private void performWrite() {
|
|
// Store initial comments so we can add them back later
|
|
List<String> initialComments = getInitialUserComments();
|
|
|
|
// Create property resource with new defaults, save with ConfigMe for proper sections & comments
|
|
PropertyResource resource = createPropertyResourceWithCommentEntries();
|
|
new SettingsManager(resource, null, MessageUpdater.getConfigurationData()).save();
|
|
|
|
// Go through the newly saved file and replace texts with comment marker to actual YAML comments
|
|
// and add initial comments back to the file
|
|
rewriteToFileWithComments(initialComments);
|
|
}
|
|
|
|
/**
|
|
* @return any custom comments at the top of the file, for later usage
|
|
*/
|
|
private List<String> getInitialUserComments() {
|
|
final List<String> initialComments = new ArrayList<>();
|
|
final String firstCommentByConfigMe = getFirstCommentByConfigMe();
|
|
|
|
for (String line : FileIoUtils.readLinesFromFile(file.toPath())) {
|
|
if (line.isEmpty() || line.startsWith("#") && !line.equals(firstCommentByConfigMe)) {
|
|
initialComments.add(line);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
// Small fix: so we can keep running this writer and get the same result, we need to make sure that any ending
|
|
// empty lines are removed
|
|
for (int i = initialComments.size() - 1; i >= 0; --i) {
|
|
if (initialComments.get(i).isEmpty()) {
|
|
initialComments.remove(i);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return initialComments;
|
|
}
|
|
|
|
/**
|
|
* @return the first comment generated by ConfigMe (comment of the first root path)
|
|
*/
|
|
private static String getFirstCommentByConfigMe() {
|
|
ConfigurationData configurationData = MessageUpdater.getConfigurationData();
|
|
String firstRootPath = configurationData.getProperties().get(0).getPath().split("\\.")[0];
|
|
return "# " + configurationData.getCommentsForSection(firstRootPath)[0];
|
|
}
|
|
|
|
/**
|
|
* @return generated {@link PropertyResource} with missing entries taken from the default file and marked
|
|
* with the {@link #COMMENT_MARKER}
|
|
*/
|
|
private PropertyResource createPropertyResourceWithCommentEntries() {
|
|
YamlFileResource resource = new MigraterYamlFileResource(file);
|
|
for (Property<?> property : MessageUpdater.getConfigurationData().getProperties()) {
|
|
String text = resource.getString(property.getPath());
|
|
if (text == null) {
|
|
resource.setValue(property.getPath(), COMMENT_MARKER + defaultFile.getString(property.getPath()));
|
|
}
|
|
}
|
|
return resource;
|
|
}
|
|
|
|
/**
|
|
* Writes to the file again, adding the provided initial comments at the top of the file and converting
|
|
* any entries marked with {@link #COMMENT_MARKER} to YAML comments.
|
|
*
|
|
* @param initialComments the comments at the top of the file to add back
|
|
*/
|
|
private void rewriteToFileWithComments(List<String> initialComments) {
|
|
List<String> newLines = new ArrayList<>(initialComments);
|
|
|
|
for (String line : FileIoUtils.readLinesFromFile(file.toPath())) {
|
|
if (line.contains(COMMENT_MARKER)) {
|
|
String lineAsYamlComment = convertLineWithCommentMarkerToYamlComment(line);
|
|
newLines.add(lineAsYamlComment);
|
|
} else if (line.startsWith("#") && !newLines.isEmpty()) {
|
|
// ConfigMe doesn't support empty line between comments, so here we check if we have a comment that
|
|
// isn't at the very top and sneak in an empty line if so.
|
|
newLines.add("");
|
|
newLines.add(line);
|
|
} else if (!line.isEmpty()) {
|
|
// ConfigMe adds an empty line at the beginning, so check here that we don't include any empty lines...
|
|
newLines.add(line);
|
|
}
|
|
}
|
|
newLines.add(""); // Makes sure file ends with new line
|
|
|
|
FileIoUtils.writeToFile(file.toPath(), String.join("\n", newLines));
|
|
}
|
|
|
|
private static String convertLineWithCommentMarkerToYamlComment(String line) {
|
|
Matcher matcher = SPACES_BEFORE_TEXT_PATTERN.matcher(line);
|
|
if (matcher.matches()) {
|
|
String spacesBefore = matcher.group(1);
|
|
return spacesBefore + "# TODO " + line.replace(COMMENT_MARKER, "").trim();
|
|
} else {
|
|
throw new IllegalStateException("Space-counting pattern unexpectedly did not match on line '" + line + "'");
|
|
}
|
|
}
|
|
}
|