All source projects

MrUltimateLibrary Source

Standalone source project / 68 files

MrUltimateLibrary is the backbone of all my plugins; it offers features that facilitate plugin creation, maintenance, and updates.

java

MrUltimateLibrary/src/main/java/eu/mrneznamy/mrultimatelibrary/config/MrLibYamlConfiguration.java

JAVA · Read-only source

package eu.mrneznamy.mrultimatelibrary.config;

import org.bukkit.configuration.file.YamlConfiguration;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * Extended YAML configuration with comment support
 * Inspired by CMILib's ConfigReader
 */
public class MrLibYamlConfiguration extends YamlConfiguration {
    
    private final Map<String, String> comments = new HashMap<>();
    private final List<String> headerComments = new ArrayList<>();
    
    /**
     * Adds a comment to a specific path
     * @param path Config path (e.g. "MrSellChests.Database.Type")
     * @param comment Comment text (without #)
     */
    public void addComment(String path, String comment) {
        if (path.equals("_HEADER_")) {
            headerComments.add(comment);
        } else {
            comments.put(path, comment);
        }
    }
    
    public Map<String, String> getComments() {
        return comments;
    }
    
    /**
     * Adds multiple comment lines to a path
     */
    public void addComments(String path, String... commentLines) {
        StringBuilder sb = new StringBuilder();
        for (String line : commentLines) {
            sb.append(line).append(System.lineSeparator());
        }
        addComment(path, sb.toString().trim());
    }
    
    /**
     * Sets header comments for the file
     */
    public void setHeaderComments(List<String> comments) {
        this.headerComments.clear();
        this.headerComments.addAll(comments);
    }
    
    @Override
    public void save(File file) throws IOException {
        if (file == null) {
            throw new IllegalArgumentException("File cannot be null");
        }
        
        file.getParentFile().mkdirs();
        
        String yaml = saveToString();
        String yamlWithComments = insertComments(yaml);
        
        try (PrintWriter writer = new PrintWriter(file, StandardCharsets.UTF_8.name())) {
            writer.write(yamlWithComments);
        }
    }
    
    /**
     * Inserts comments into YAML string
     */
    private String insertComments(String yaml) {
        if (comments.isEmpty() && headerComments.isEmpty()) {
            return yaml;
        }
        
        StringBuilder result = new StringBuilder();
        
        if (!headerComments.isEmpty()) {
            for (String comment : headerComments) {
                result.append(comment).append(System.lineSeparator());
            }
            result.append(System.lineSeparator());
        }
        
        String[] lines = yaml.split(System.lineSeparator());
        StringBuilder currentPath = new StringBuilder();
        int depth = 0;
        
        for (String line : lines) {
            if (line.trim().isEmpty() && result.length() == 0) {
                continue;
            }
            
            if (isKeyLine(line)) {
                int lineDepth = getDepth(line);
                String key = extractKey(line);
                
                if (key != null && !key.isEmpty()) {
                    updatePath(currentPath, key, lineDepth, depth);
                    depth = lineDepth;
                    
                    String comment = comments.get(currentPath.toString());
                    if (comment != null && !comment.isEmpty()) {
                        String indent = getIndent(lineDepth);
                        String[] commentLines = comment.split(System.lineSeparator());
                        for (String commentLine : commentLines) {
                            result.append(indent).append(commentLine).append(System.lineSeparator());
                        }
                    }
                }
            }
            
            result.append(line).append(System.lineSeparator());
        }
        
        return result.toString();
    }
    
    /**
     * Checks if line is a key line
     */
    private boolean isKeyLine(String line) {
        String trimmed = line.trim();
        return !trimmed.isEmpty() && 
               !trimmed.startsWith("#") && 
               !trimmed.startsWith("-") &&
               (trimmed.contains(": ") || trimmed.endsWith(":"));
    }
    
    /**
     * Gets the depth (indentation level) of a line
     */
    private int getDepth(String line) {
        int spaces = 0;
        for (char c : line.toCharArray()) {
            if (c == ' ') {
                spaces++;
            } else {
                break;
            }
        }
        return spaces / 2;
    }
    
    /**
     * Extracts the key from a line
     */
    private String extractKey(String line) {
        String trimmed = line.trim();
        int colonIndex = trimmed.indexOf(':');
        if (colonIndex > 0) {
            return trimmed.substring(0, colonIndex).trim();
        }
        return null;
    }
    
    /**
     * Updates the current path based on depth
     */
    private void updatePath(StringBuilder currentPath, String key, int newDepth, int oldDepth) {
        if (newDepth == 0) {
            currentPath.setLength(0);
            currentPath.append(key);
        } else if (newDepth > oldDepth) {
            currentPath.append(".").append(key);
        } else if (newDepth < oldDepth) {
            int levelsUp = oldDepth - newDepth;
            for (int i = 0; i < levelsUp; i++) {
                int lastDot = currentPath.lastIndexOf(".");
                if (lastDot > 0) {
                    currentPath.setLength(lastDot);
                }
            }
            int lastDot = currentPath.lastIndexOf(".");
            if (lastDot > 0) {
                currentPath.setLength(lastDot + 1);
                currentPath.append(key);
            } else {
                currentPath.setLength(0);
                currentPath.append(key);
            }
        } else {
            int lastDot = currentPath.lastIndexOf(".");
            if (lastDot > 0) {
                currentPath.setLength(lastDot + 1);
                currentPath.append(key);
            } else {
                currentPath.setLength(0);
                currentPath.append(key);
            }
        }
    }
    
    /**
     * Gets indentation string for a given depth
     */
    private String getIndent(int depth) {
        StringBuilder indent = new StringBuilder();
        for (int i = 0; i < depth * 2; i++) {
            indent.append(" ");
        }
        return indent.toString();
    }
    
    /**
     * Loads configuration from file and preserves comments
     */
    public void loadWithComments(File file) throws Exception {
        this.load(file);
    }
}
216 linesGNU GENERAL PUBLIC LICENSE · Version 3, 29 June 2007 · UTF-8 · Read only