package net.shockverse.survivalgames.extras; import net.shockverse.survivalgames.core.Tools; import net.shockverse.survivalgames.core.Logger; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Scanner; import net.shockverse.survivalgames.exceptions.PropertyException; /** * @description Manipulates a properties file * @author TaylorKelly */ public class PropertyFile { public static PropertyFile getFile(String pathFile) { return propFiles.get(pathFile); } public static String getShortcut(PropertyEntry entry) { String shortcut = entry.getKey(); while(entry.getParent() != null && entry.getParent().getKey() != null) { shortcut = entry.getParent().getKey() + "." + shortcut; entry = entry.getParent(); } return shortcut; } private static HashMap<String, PropertyFile> propFiles = new HashMap<String, PropertyFile>(); private HashMap<String, PropertyEntry> propShortcuts; private PropertyList properties; private File file; private int lineNumber; private PropertyEntry lastEntry; public PropertyFile(String configPath, String fileName) { this(configPath, new File(fileName)); } public PropertyFile(String configPath, String path, String fileName) { this(configPath, new File(path, fileName)); } public PropertyFile(String configPath, File file) { this.file = file; properties = new PropertyList(this, null, null, null); propShortcuts = new HashMap<String, PropertyEntry>(); propFiles.put(configPath, this); } public HashMap<String, PropertyEntry> getShortcuts() { return propShortcuts; } public PropertyEntry getProperty(String shortcut) { return propShortcuts.get(shortcut); } public void loadProperties() throws IOException, PropertyException { lineNumber = 0; if (!file.exists()) { file.createNewFile(); } Scanner scan = new Scanner(file); properties = loadPropertyList(scan); } protected PropertyList loadPropertyList(Scanner scan) throws PropertyException { return loadPropertyList(scan, null, null, null); } protected PropertyList loadPropertyList(Scanner scan, PropertyList parent, String lkey, String lcomment) throws PropertyException { PropertyList list = new PropertyList(this, parent, lkey, lcomment); propShortcuts.put(getShortcut(list), list); String line = ""; while (scan.hasNextLine()) { lineNumber++; line = scan.nextLine().trim(); if (line.startsWith("}")) { break; } if ((!line.contains("=") && !line.contains("{") && !line.contains("+")) || line.startsWith("#")) { continue; } if (!line.contains("{")) { if(line.startsWith("+")) { String value = line.substring(line.indexOf("+") + 1).trim().replaceAll("\\\\'", "&"e&&"); lastEntry.appendValue(value.replaceAll("'", "").replaceAll("&"e&&", "'")); } else { int equals = line.indexOf("="); int commentIndex = line.length(); if (line.contains("#")) { commentIndex = line.indexOf("#"); } String key = line.substring(0, equals).trim(); if (key.equals("")) { continue; } String value = line.substring(equals + 1, commentIndex).trim().replaceAll("\\\\'", "&"e&&"); int quoteProblems = Tools.countString("'", value) - 2; if (!value.startsWith("'")) { quoteProblems++; } if (!value.endsWith("'")) { quoteProblems++; } if (quoteProblems > 0) { String source = key; if(lkey != null) source = lkey + "(" + key + ")"; throw new PropertyException("Unable to parse file " + file.getName() + ".\n\t Missing/extra single quote(s) for " + source + " on line " + lineNumber + ".\n\tNote: To have single quotes in a value you must escape the quote like so:\n\t\texample = 'This isn\\'t a bad example.'"); } value = value.replaceAll("'", "").replaceAll("&"e&&", "'"); String comment = ""; if (commentIndex < line.length() - 1) { comment = line.substring(commentIndex + 1, line.length()).trim(); } lastEntry = new PropertyEntry(list, key, value, comment); list.addProperty(lastEntry); } } else { int bracket = line.indexOf("{"); int commentIndex = line.length(); if (line.contains("#")) { commentIndex = line.indexOf("#"); } String key = line.substring(0, bracket).trim(); String comment = ""; if (commentIndex < line.length() - 1) { comment = line.substring(commentIndex + 1, line.length()).trim(); } if (key == null || key.trim().equals("")) { throw new PropertyException("Unable to parse file " + file.getName() + ".\n\tOpening bracket '{' must be on the same line as the array name."); } list.addProperty(loadPropertyList(scan, list, key, comment)); } if (!scan.hasNextLine() && lkey != null) { throw new PropertyException("Unable to parse file " + file.getName() + ".\n\tMissing closing braket '}'."); } } return list; } public PropertyList getProperties() { return properties; } public void saveProperties() { BufferedWriter bwriter = null; FileWriter fwriter = null; try { if (file.exists()) { file.delete(); file.createNewFile(); } fwriter = new FileWriter(file); bwriter = new BufferedWriter(fwriter); saveProperties(bwriter, properties, 0); bwriter.flush(); } catch (IOException e) { Logger.error("Could not save " + file.getName() + ". Reload the plugin to get a fresh copy."); } finally { try { if (bwriter != null) { bwriter.flush(); bwriter.close(); } if (fwriter != null) { fwriter.close(); } } catch (IOException e) { Logger.error("IO Exception with file " + file.getName() + " (on close)."); } } } protected void saveProperties(BufferedWriter bwriter, PropertyList list, int indent) throws IOException { if (list.getKey() != null && indent != 0) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < indent - 1; i++) { builder.append(" "); } if(!list.isModified()) { builder.append("# "); } builder.append(list.getKey()); builder.append(" {"); if (!list.getComment().equals("")) { builder.append(" # "); builder.append(list.getComment()); } bwriter.write(builder.toString()); bwriter.newLine(); } for (PropertyEntry entry : list.getProperties()) { StringBuilder builder = new StringBuilder(); List<String> multiLineVals = new ArrayList<String>(); if (entry.getKey().equals("\\n")) { bwriter.newLine(); continue; } if (entry instanceof PropertyList) { saveProperties(bwriter, (PropertyList) entry, indent + 1); } else { for (int i = 0; i < indent; i++) { builder.append(" "); } if(!entry.isModified() && !entry.getKey().equals("#")) { builder.append("# "); } if (!entry.getKey().equals("#")) { String val = entry.getValue(); if(entry.getValue().contains("\n")) { String[] split = entry.getValue().split("\\n"); if(split != null) { if(split.length > 0 && !Tools.isNullEmpty(split[0])) { val = split[0]; } for(int i = 1; i < split.length; i++) { if(!Tools.isNullEmpty(split[i])) multiLineVals.add(split[i].replaceAll("\\\\'", "&"e&&").replaceAll("'", "\\\\'").replaceAll("&"e&&", "\\\\'")); } } } builder.append(entry.getKey()); builder.append(" = "); builder.append("'"); builder.append(val.replaceAll("\\\\'", "&"e&&").replaceAll("'", "\\\\'").replaceAll("&"e&&", "\\\\'")); builder.append("'"); } else { builder.append(entry.getKey()); } if (!entry.getComment().equals("")) { if (!entry.getKey().equals("#")) { builder.append(" #"); } builder.append(" "); builder.append(entry.getComment()); } } bwriter.write(builder.toString()); bwriter.newLine(); for(String val : multiLineVals) { builder = new StringBuilder(); if(!entry.isModified() && !entry.getKey().equals("#")) { builder.append("# "); } for (int i = 0; i < indent - 1 + 2; i++) { builder.append(" "); } builder.append("+ "); builder.append("'"); builder.append(val); builder.append("'"); bwriter.write(builder.toString()); bwriter.newLine(); } multiLineVals.clear(); } if (indent != 0) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < indent - 1; i++) { builder.append(" "); } if(!list.isModified()) { builder.append("# "); } builder.append("}"); bwriter.write(builder.toString()); } } }