parent
5e35bfe958
commit
cc85d8a9d3
@ -0,0 +1,11 @@ |
||||
package mightypork.gamecore.control.interf; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
|
||||
@Documented |
||||
@Retention(RetentionPolicy.SOURCE) |
||||
public @interface NoImpl { |
||||
|
||||
} |
@ -0,0 +1,60 @@ |
||||
package mightypork.gamecore.render; |
||||
|
||||
|
||||
import java.awt.image.BufferedImage; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.nio.ByteBuffer; |
||||
|
||||
import javax.imageio.ImageIO; |
||||
|
||||
|
||||
/** |
||||
* Screenshot object, can be used to extract image or write to file.<br> |
||||
* Screenshot, once taken, can be safely processed in separate thread. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class Screenshot { |
||||
|
||||
private int width; |
||||
private int height; |
||||
private int bpp; |
||||
private ByteBuffer bytes; |
||||
private BufferedImage image; |
||||
|
||||
|
||||
public Screenshot(int width, int height, int bpp, ByteBuffer buffer) { |
||||
this.width = width; |
||||
this.height = height; |
||||
this.bpp = bpp; |
||||
this.bytes = buffer; |
||||
} |
||||
|
||||
|
||||
public BufferedImage getImage() |
||||
{ |
||||
if (image != null) return image; |
||||
|
||||
image = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB); |
||||
|
||||
// convert to a buffered image
|
||||
for (int x = 0; x < this.width; x++) { |
||||
for (int y = 0; y < this.height; y++) { |
||||
final int i = (x + (this.width * y)) * this.bpp; |
||||
final int r = this.bytes.get(i) & 0xFF; |
||||
final int g = this.bytes.get(i + 1) & 0xFF; |
||||
final int b = this.bytes.get(i + 2) & 0xFF; |
||||
image.setRGB(x, this.height - (y + 1), (0xFF << 24) | (r << 16) | (g << 8) | b); |
||||
} |
||||
} |
||||
|
||||
return image; |
||||
} |
||||
|
||||
|
||||
public void save(File file) throws IOException |
||||
{ |
||||
ImageIO.write(getImage(), "PNG", file); |
||||
} |
||||
} |
@ -0,0 +1,450 @@ |
||||
package mightypork.utils.config; |
||||
|
||||
|
||||
import java.io.*; |
||||
import java.util.*; |
||||
import java.util.Map.Entry; |
||||
|
||||
import mightypork.utils.math.Range; |
||||
import mightypork.utils.math.coord.Coord; |
||||
import mightypork.utils.objects.Convert; |
||||
|
||||
|
||||
/** |
||||
* Property manager with advanced formatting and value checking.<br> |
||||
* Methods starting with put are for filling. Most of the others are shortcuts |
||||
* to getters. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class PropertyManager { |
||||
|
||||
private abstract class Property<T> { |
||||
|
||||
public String comment; |
||||
public String key; |
||||
|
||||
public T value; |
||||
public T defaultValue; |
||||
|
||||
|
||||
public Property(String key, T defaultValue, String comment) { |
||||
super(); |
||||
this.comment = comment; |
||||
this.key = key; |
||||
this.defaultValue = defaultValue; |
||||
this.value = defaultValue; |
||||
} |
||||
|
||||
|
||||
public abstract void parse(String string); |
||||
|
||||
|
||||
@Override |
||||
public String toString() |
||||
{ |
||||
return Convert.toString(value); |
||||
} |
||||
} |
||||
|
||||
private class BooleanProperty extends Property<Boolean> { |
||||
|
||||
public BooleanProperty(String key, Boolean defaultValue, String comment) { |
||||
super(key, defaultValue, comment); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void parse(String string) |
||||
{ |
||||
value = Convert.toBoolean(string, defaultValue); |
||||
} |
||||
} |
||||
|
||||
private class IntegerProperty extends Property<Integer> { |
||||
|
||||
public IntegerProperty(String key, Integer defaultValue, String comment) { |
||||
super(key, defaultValue, comment); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void parse(String string) |
||||
{ |
||||
value = Convert.toInteger(string, defaultValue); |
||||
} |
||||
} |
||||
|
||||
private class DoubleProperty extends Property<Double> { |
||||
|
||||
public DoubleProperty(String key, Double defaultValue, String comment) { |
||||
super(key, defaultValue, comment); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void parse(String string) |
||||
{ |
||||
value = Convert.toDouble(string, defaultValue); |
||||
} |
||||
} |
||||
|
||||
private class StringProperty extends Property<String> { |
||||
|
||||
public StringProperty(String key, String defaultValue, String comment) { |
||||
super(key, defaultValue, comment); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void parse(String string) |
||||
{ |
||||
value = Convert.toString(string, defaultValue); |
||||
} |
||||
} |
||||
|
||||
private class RangeProperty extends Property<Range> { |
||||
|
||||
public RangeProperty(String key, Range defaultValue, String comment) { |
||||
super(key, defaultValue, comment); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void parse(String string) |
||||
{ |
||||
value = Convert.toRange(string, defaultValue); |
||||
} |
||||
} |
||||
|
||||
private class CoordProperty extends Property<Coord> { |
||||
|
||||
public CoordProperty(String key, Coord defaultValue, String comment) { |
||||
super(key, defaultValue, comment); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void parse(String string) |
||||
{ |
||||
value = Convert.toCoord(string, defaultValue); |
||||
} |
||||
} |
||||
|
||||
/** put newline before entry comments */ |
||||
private boolean cfgNewlineBeforeComments = true; |
||||
/** Put newline between sections. */ |
||||
private boolean cfgSeparateSections = true; |
||||
/** Force save, even if nothing changed (used to save changed comments) */ |
||||
private boolean cfgForceSave; |
||||
|
||||
private final File file; |
||||
private String fileComment = ""; |
||||
|
||||
private final TreeMap<String, Property<?>> entries; |
||||
private final TreeMap<String, String> renameTable; |
||||
private final TreeMap<String, String> overrideValues; |
||||
private SortedProperties props = new SortedProperties(); |
||||
|
||||
|
||||
/** |
||||
* Create property manager from file path and an initial comment. |
||||
* |
||||
* @param file file with the props |
||||
* @param comment the initial comment. Use \n in it if you want. |
||||
*/ |
||||
public PropertyManager(File file, String comment) { |
||||
this.file = file; |
||||
this.entries = new TreeMap<String, Property<?>>(); |
||||
this.overrideValues = new TreeMap<String, String>(); |
||||
this.renameTable = new TreeMap<String, String>(); |
||||
this.fileComment = comment; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Load, fix and write to file. |
||||
*/ |
||||
public void apply() |
||||
{ |
||||
boolean needsSave = false; |
||||
FileInputStream fis = null; |
||||
try { |
||||
new File(file.getParent()).mkdirs(); |
||||
fis = new FileInputStream(file); |
||||
props.load(fis); |
||||
|
||||
} catch (final IOException e) { |
||||
needsSave = true; |
||||
props = new SortedProperties(); |
||||
} finally { |
||||
try { |
||||
if (fis != null) fis.close(); |
||||
} catch (final IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
props.cfgBlankRowBetweenSections = cfgSeparateSections; |
||||
props.cfgBlankRowBeforeComment = cfgNewlineBeforeComments; |
||||
|
||||
final ArrayList<String> keyList = new ArrayList<String>(); |
||||
|
||||
// rename keys
|
||||
for (final Entry<String, String> entry : renameTable.entrySet()) { |
||||
if (props.getProperty(entry.getKey()) == null) { |
||||
continue; |
||||
} |
||||
props.setProperty(entry.getValue(), props.getProperty(entry.getKey())); |
||||
props.remove(entry.getKey()); |
||||
needsSave = true; |
||||
} |
||||
|
||||
// set the override values into the freshly loaded properties file
|
||||
for (final Entry<String, String> entry : overrideValues.entrySet()) { |
||||
props.setProperty(entry.getKey(), entry.getValue()); |
||||
needsSave = true; |
||||
} |
||||
|
||||
// validate entries one by one, replace with default when needed
|
||||
for (final Property<?> entry : entries.values()) { |
||||
keyList.add(entry.key); |
||||
|
||||
final String propOrig = props.getProperty(entry.key); |
||||
|
||||
entry.parse(propOrig); |
||||
|
||||
if (!entry.toString().equals(propOrig)) { |
||||
needsSave = true; |
||||
} |
||||
|
||||
if (entry.comment != null) { |
||||
props.setKeyComment(entry.key, entry.comment); |
||||
} |
||||
|
||||
if (propOrig == null || !entry.toString().equals(propOrig)) { |
||||
props.setProperty(entry.key, entry.toString()); |
||||
|
||||
needsSave = true; |
||||
} |
||||
} |
||||
|
||||
// removed unused props
|
||||
for (final String propname : props.keySet().toArray(new String[props.size()])) { |
||||
if (!keyList.contains(propname)) { |
||||
props.remove(propname); |
||||
needsSave = true; |
||||
} |
||||
|
||||
} |
||||
|
||||
// save if needed
|
||||
if (needsSave || cfgForceSave) { |
||||
try { |
||||
props.store(new FileOutputStream(file), fileComment); |
||||
} catch (final IOException ioe) { |
||||
ioe.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
overrideValues.clear(); |
||||
renameTable.clear(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param newlineBeforeComments put newline before comments |
||||
*/ |
||||
public void cfgNewlineBeforeComments(boolean newlineBeforeComments) |
||||
{ |
||||
this.cfgNewlineBeforeComments = newlineBeforeComments; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param separateSections do separate sections by newline |
||||
*/ |
||||
public void cfgSeparateSections(boolean separateSections) |
||||
{ |
||||
this.cfgSeparateSections = separateSections; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param forceSave save even if unchanged. |
||||
*/ |
||||
public void cfgForceSave(boolean forceSave) |
||||
{ |
||||
this.cfgForceSave = forceSave; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get a property entry (rarely used) |
||||
* |
||||
* @param n key |
||||
* @return the entry |
||||
*/ |
||||
private Property<?> get(String n) |
||||
{ |
||||
try { |
||||
return entries.get(n); |
||||
} catch (final Throwable t) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get boolean property |
||||
* |
||||
* @param n key |
||||
* @return the boolean found, or false |
||||
*/ |
||||
public Boolean getBoolean(String n) |
||||
{ |
||||
return Convert.toBoolean(get(n).value); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get numeric property |
||||
* |
||||
* @param n key |
||||
* @return the int found, or null |
||||
*/ |
||||
public Integer getInteger(String n) |
||||
{ |
||||
return Convert.toInteger(get(n).value); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get numeric property as double |
||||
* |
||||
* @param n key |
||||
* @return the double found, or null |
||||
*/ |
||||
public Double getDouble(String n) |
||||
{ |
||||
return Convert.toDouble(get(n).value); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get string property |
||||
* |
||||
* @param n key |
||||
* @return the string found, or null |
||||
*/ |
||||
public String getString(String n) |
||||
{ |
||||
return Convert.toString(get(n).value); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a boolean property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putBoolean(String n, boolean d, String comment) |
||||
{ |
||||
entries.put(n, new BooleanProperty(n, d, comment)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a numeric property (double) |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putDouble(String n, double d, String comment) |
||||
{ |
||||
entries.put(n, new DoubleProperty(n, d, comment)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a numeric property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putInteger(String n, int d, String comment) |
||||
{ |
||||
entries.put(n, new IntegerProperty(n, d, comment)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a string property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putString(String n, String d, String comment) |
||||
{ |
||||
entries.put(n, new StringProperty(n, d, comment)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a coord property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putCoord(String n, Coord d, String comment) |
||||
{ |
||||
entries.put(n, new CoordProperty(n, d, comment)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a range property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putRange(String n, Range d, String comment) |
||||
{ |
||||
entries.put(n, new RangeProperty(n, d, comment)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Rename key before doing "apply"; value is preserved |
||||
* |
||||
* @param oldKey old key |
||||
* @param newKey new key |
||||
*/ |
||||
public void renameKey(String oldKey, String newKey) |
||||
{ |
||||
renameTable.put(oldKey, newKey); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Set value saved to certain key; use to save runtime-changed configuration |
||||
* values. |
||||
* |
||||
* @param key key |
||||
* @param value the saved value |
||||
*/ |
||||
public void setValue(String key, Object value) |
||||
{ |
||||
overrideValues.put(key, value.toString()); |
||||
return; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,303 @@ |
||||
package mightypork.utils.config; |
||||
|
||||
|
||||
import java.io.*; |
||||
import java.util.Collections; |
||||
import java.util.Enumeration; |
||||
import java.util.Hashtable; |
||||
import java.util.Vector; |
||||
|
||||
|
||||
/** |
||||
* Properties stored in file, alphabetically sorted.<br> |
||||
* Uses UTF-8 encoding and each property can have it's own comment. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class SortedProperties extends java.util.Properties { |
||||
|
||||
/** Option: put empty line before each comment. */ |
||||
public boolean cfgBlankRowBeforeComment = true; |
||||
|
||||
/** |
||||
* Option: Separate sections by newline<br> |
||||
* Section = string before first dot in key. |
||||
*/ |
||||
public boolean cfgBlankRowBetweenSections = true; |
||||
|
||||
/** Comments for individual keys */ |
||||
private final Hashtable<String, String> keyComments = new Hashtable<String, String>(); |
||||
|
||||
|
||||
private static void writeComments(BufferedWriter bw, String comm) throws IOException |
||||
{ |
||||
final String comments = comm.replace("\n\n", "\n \n"); |
||||
|
||||
final int len = comments.length(); |
||||
int current = 0; |
||||
int last = 0; |
||||
final char[] uu = new char[6]; |
||||
uu[0] = '\\'; |
||||
uu[1] = 'u'; |
||||
while (current < len) { |
||||
final char c = comments.charAt(current); |
||||
if (c > '\u00ff' || c == '\n' || c == '\r') { |
||||
if (last != current) { |
||||
bw.write("# " + comments.substring(last, current)); |
||||
} |
||||
|
||||
if (c > '\u00ff') { |
||||
uu[2] = hexDigit(c, 12); |
||||
uu[3] = hexDigit(c, 8); |
||||
uu[4] = hexDigit(c, 4); |
||||
uu[5] = hexDigit(c, 0); |
||||
bw.write(new String(uu)); |
||||
} else { |
||||
bw.newLine(); |
||||
if (c == '\r' && current != len - 1 && comments.charAt(current + 1) == '\n') { |
||||
current++; |
||||
} |
||||
} |
||||
last = current + 1; |
||||
} |
||||
current++; |
||||
} |
||||
if (last != current) { |
||||
bw.write("# " + comments.substring(last, current)); |
||||
} |
||||
|
||||
bw.newLine(); |
||||
bw.newLine(); |
||||
bw.newLine(); |
||||
} |
||||
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" }) |
||||
@Override |
||||
public synchronized Enumeration keys() |
||||
{ |
||||
final Enumeration keysEnum = super.keys(); |
||||
final Vector keyList = new Vector(); |
||||
while (keysEnum.hasMoreElements()) { |
||||
keyList.add(keysEnum.nextElement()); |
||||
} |
||||
Collections.sort(keyList); //sort!
|
||||
return keyList.elements(); |
||||
} |
||||
|
||||
|
||||
private static String saveConvert(String theString, boolean escapeSpace, boolean escapeUnicode) |
||||
{ |
||||
final int len = theString.length(); |
||||
int bufLen = len * 2; |
||||
if (bufLen < 0) { |
||||
bufLen = Integer.MAX_VALUE; |
||||
} |
||||
final StringBuffer result = new StringBuffer(bufLen); |
||||
|
||||
for (int x = 0; x < len; x++) { |
||||
final char ch = theString.charAt(x); |
||||
|
||||
// Handle common case first, selecting largest block that
|
||||
// avoids the specials below
|
||||
if ((ch > 61) && (ch < 127)) { |
||||
if (ch == '\\') { |
||||
result.append('\\'); |
||||
result.append('\\'); |
||||
continue; |
||||
} |
||||
result.append(ch); |
||||
continue; |
||||
} |
||||
|
||||
switch (ch) { |
||||
case ' ': |
||||
if (x == 0 || escapeSpace) { |
||||
result.append('\\'); |
||||
} |
||||
result.append(' '); |
||||
break; |
||||
|
||||
case '\t': |
||||
result.append('\\'); |
||||
result.append('t'); |
||||
break; |
||||
|
||||
case '\n': |
||||
result.append('\\'); |
||||
result.append('n'); |
||||
break; |
||||
|
||||
case '\r': |
||||
result.append('\\'); |
||||
result.append('r'); |
||||
break; |
||||
|
||||
case '\f': |
||||
result.append('\\'); |
||||
result.append('f'); |
||||
break; |
||||
|
||||
case '=': // Fall through
|
||||
case ':': // Fall through
|
||||
case '#': // Fall through
|
||||
case '!': |
||||
result.append('\\'); |
||||
result.append(ch); |
||||
break; |
||||
|
||||
default: |
||||
if (((ch < 0x0020) || (ch > 0x007e)) & escapeUnicode) { |
||||
result.append('\\'); |
||||
result.append('u'); |
||||
result.append(hexDigit(ch, 12)); |
||||
result.append(hexDigit(ch, 8)); |
||||
result.append(hexDigit(ch, 4)); |
||||
result.append(hexDigit(ch, 0)); |
||||
} else { |
||||
result.append(ch); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return result.toString(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Set additional comment to a key |
||||
* |
||||
* @param key key for comment |
||||
* @param comment the comment |
||||
*/ |
||||
public void setKeyComment(String key, String comment) |
||||
{ |
||||
keyComments.put(key, comment); |
||||
} |
||||
|
||||
|
||||
@SuppressWarnings("rawtypes") |
||||
@Override |
||||
public void store(OutputStream out, String comments) throws IOException |
||||
{ |
||||
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); |
||||
|
||||
final boolean escUnicode = false; |
||||
boolean firstEntry = true; |
||||
String lastSectionBeginning = ""; |
||||
|
||||
if (comments != null) { |
||||
writeComments(bw, comments); |
||||
} |
||||
|
||||
synchronized (this) { |
||||
for (final Enumeration e = keys(); e.hasMoreElements();) { |
||||
boolean wasNewLine = false; |
||||
|
||||
String key = (String) e.nextElement(); |
||||
String val = (String) get(key); |
||||
key = saveConvert(key, true, escUnicode); |
||||
val = saveConvert(val, false, escUnicode); |
||||
|
||||
if (cfgBlankRowBetweenSections && !lastSectionBeginning.equals(key.split("[.]")[0])) { |
||||
if (!firstEntry) { |
||||
bw.newLine(); |
||||
bw.newLine(); |
||||
} |
||||
|
||||
wasNewLine = true; |
||||
lastSectionBeginning = key.split("[.]")[0]; |
||||
} |
||||
|
||||
if (keyComments.containsKey(key)) { |
||||
String cm = keyComments.get(key); |
||||
cm = cm.replace("\r", "\n"); |
||||
cm = cm.replace("\r\n", "\n"); |
||||
cm = cm.replace("\n\n", "\n \n"); |
||||
|
||||
final String[] cmlines = cm.split("\n"); |
||||
|
||||
if (!wasNewLine && !firstEntry && cfgBlankRowBeforeComment) { |
||||
bw.newLine(); |
||||
} |
||||
|
||||
for (final String cmline : cmlines) { |
||||
bw.write("# " + cmline); |
||||
bw.newLine(); |
||||
} |
||||
} |
||||
|
||||
bw.write(key + " = " + val); |
||||
bw.newLine(); |
||||
|
||||
firstEntry = false; |
||||
} |
||||
} |
||||
bw.flush(); |
||||
} |
||||
|
||||
|
||||
private static String escapifyStr(String str) |
||||
{ |
||||
final StringBuilder result = new StringBuilder(); |
||||
|
||||
final int len = str.length(); |
||||
for (int x = 0; x < len; x++) { |
||||
final char ch = str.charAt(x); |
||||
if (ch <= 0x007e) { |
||||
result.append(ch); |
||||
continue; |
||||
} |
||||
|
||||
result.append('\\'); |
||||
result.append('u'); |
||||
result.append(hexDigit(ch, 12)); |
||||
result.append(hexDigit(ch, 8)); |
||||
result.append(hexDigit(ch, 4)); |
||||
result.append(hexDigit(ch, 0)); |
||||
} |
||||
return result.toString(); |
||||
} |
||||
|
||||
|
||||
private static char hexDigit(char ch, int offset) |
||||
{ |
||||
final int val = (ch >> offset) & 0xF; |
||||
if (val <= 9) { |
||||
return (char) ('0' + val); |
||||
} |
||||
|
||||
return (char) ('A' + val - 10); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void load(InputStream is) throws IOException |
||||
{ |
||||
load(is, "utf-8"); |
||||
} |
||||
|
||||
|
||||
public void load(InputStream is, String encoding) throws IOException |
||||
{ |
||||
final StringBuilder sb = new StringBuilder(); |
||||
final InputStreamReader isr = new InputStreamReader(is, encoding); |
||||
while (true) { |
||||
final int temp = isr.read(); |
||||
if (temp < 0) { |
||||
break; |
||||
} |
||||
|
||||
final char c = (char) temp; |
||||
sb.append(c); |
||||
} |
||||
|
||||
final String read = sb.toString(); |
||||
|
||||
final String inputString = escapifyStr(read); |
||||
final byte[] bs = inputString.getBytes("ISO-8859-1"); |
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(bs); |
||||
|
||||
super.load(bais); |
||||
} |
||||
} |
@ -1,963 +0,0 @@ |
||||
package mightypork.utils.files; |
||||
|
||||
|
||||
import java.io.*; |
||||
import java.util.*; |
||||
import java.util.Map.Entry; |
||||
|
||||
import mightypork.utils.math.Calc; |
||||
|
||||
|
||||
/** |
||||
* Property manager with advanced formatting and value checking.<br> |
||||
* Methods starting with put are for filling. Most of the others are shortcuts |
||||
* to getters. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class PropertyManager { |
||||
|
||||
/** |
||||
* Properties stored in file, alphabetically sorted.<br> |
||||
* Property file is much cleaner than the normal java.util.Properties, |
||||
* newlines can be inserted to separate categories, and individual keys can |
||||
* have their own inline comments. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
private static class SortedProperties extends Properties { |
||||
|
||||
/** A table of hex digits */ |
||||
private static final char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; |
||||
|
||||
|
||||
/** |
||||
* this is here because the original method is private. |
||||
* |
||||
* @param nibble |
||||
* @return hex char. |
||||
*/ |
||||
private static char toHex(int nibble) |
||||
{ |
||||
return hexChars[(nibble & 0xF)]; |
||||
} |
||||
|
||||
|
||||
private static void writeComments(BufferedWriter bw, String comm) throws IOException |
||||
{ |
||||
final String comments = comm.replace("\n\n", "\n \n"); |
||||
|
||||
final int len = comments.length(); |
||||
int current = 0; |
||||
int last = 0; |
||||
final char[] uu = new char[6]; |
||||
uu[0] = '\\'; |
||||
uu[1] = 'u'; |
||||
while (current < len) { |
||||
final char c = comments.charAt(current); |
||||
if (c > '\u00ff' || c == '\n' || c == '\r') { |
||||
if (last != current) { |
||||
bw.write("# " + comments.substring(last, current)); |
||||
} |
||||
|
||||
if (c > '\u00ff') { |
||||
uu[2] = toHex((c >> 12) & 0xf); |
||||
uu[3] = toHex((c >> 8) & 0xf); |
||||
uu[4] = toHex((c >> 4) & 0xf); |
||||
uu[5] = toHex(c & 0xf); |
||||
bw.write(new String(uu)); |
||||
} else { |
||||
bw.newLine(); |
||||
if (c == '\r' && current != len - 1 && comments.charAt(current + 1) == '\n') { |
||||
current++; |
||||
} |
||||
} |
||||
last = current + 1; |
||||
} |
||||
current++; |
||||
} |
||||
if (last != current) { |
||||
bw.write("# " + comments.substring(last, current)); |
||||
} |
||||
bw.newLine(); |
||||
bw.newLine(); |
||||
bw.newLine(); |
||||
} |
||||
|
||||
/** Option: put empty line before each comment. */ |
||||
public boolean cfgEmptyLineBeforeComment = true; |
||||
|
||||
/** |
||||
* Option: Separate sections by newline<br> |
||||
* Section = string before first dot in key. |
||||
*/ |
||||
public boolean cfgSeparateSectionsByEmptyLine = true; |
||||
|
||||
private boolean firstEntry = true; |
||||
|
||||
/** Comments for individual keys */ |
||||
private final Hashtable<String, String> keyComments = new Hashtable<String, String>(); |
||||
|
||||
private String lastSectionBeginning = ""; |
||||
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" }) |
||||
@Override |
||||
public synchronized Enumeration keys() |
||||
{ |
||||
final Enumeration keysEnum = super.keys(); |
||||
final Vector keyList = new Vector(); |
||||
while (keysEnum.hasMoreElements()) { |
||||
keyList.add(keysEnum.nextElement()); |
||||
} |
||||
Collections.sort(keyList); |
||||
return keyList.elements(); |
||||
} |
||||
|
||||
|
||||
private static String saveConvert(String theString, boolean escapeSpace, boolean escapeUnicode) |
||||
{ |
||||
final int len = theString.length(); |
||||
int bufLen = len * 2; |
||||
if (bufLen < 0) { |
||||
bufLen = Integer.MAX_VALUE; |
||||
} |
||||
final StringBuffer outBuffer = new StringBuffer(bufLen); |
||||
|
||||
for (int x = 0; x < len; x++) { |
||||
final char aChar = theString.charAt(x); |
||||
|
||||
// Handle common case first, selecting largest block that
|
||||
// avoids the specials below
|
||||
if ((aChar > 61) && (aChar < 127)) { |
||||
if (aChar == '\\') { |
||||
outBuffer.append('\\'); |
||||
outBuffer.append('\\'); |
||||
continue; |
||||
} |
||||
outBuffer.append(aChar); |
||||
continue; |
||||
} |
||||
|
||||
switch (aChar) { |
||||
case ' ': |
||||
if (x == 0 || escapeSpace) { |
||||
outBuffer.append('\\'); |
||||
} |
||||
outBuffer.append(' '); |
||||
break; |
||||
|
||||
case '\t': |
||||
outBuffer.append('\\'); |
||||
outBuffer.append('t'); |
||||
break; |
||||
|
||||
case '\n': |
||||
outBuffer.append('\\'); |
||||
outBuffer.append('n'); |
||||
break; |
||||
|
||||
case '\r': |
||||
outBuffer.append('\\'); |
||||
outBuffer.append('r'); |
||||
break; |
||||
|
||||
case '\f': |
||||
outBuffer.append('\\'); |
||||
outBuffer.append('f'); |
||||
break; |
||||
|
||||
case '=': // Fall through
|
||||
case ':': // Fall through
|
||||
case '#': // Fall through
|
||||
case '!': |
||||
outBuffer.append('\\'); |
||||
outBuffer.append(aChar); |
||||
break; |
||||
|
||||
default: |
||||
if (((aChar < 0x0020) || (aChar > 0x007e)) & escapeUnicode) { |
||||
outBuffer.append('\\'); |
||||
outBuffer.append('u'); |
||||
outBuffer.append(toHex((aChar >> 12) & 0xF)); |
||||
outBuffer.append(toHex((aChar >> 8) & 0xF)); |
||||
outBuffer.append(toHex((aChar >> 4) & 0xF)); |
||||
outBuffer.append(toHex(aChar & 0xF)); |
||||
} else { |
||||
outBuffer.append(aChar); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return outBuffer.toString(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Set additional comment to a key |
||||
* |
||||
* @param key key for comment |
||||
* @param comment the comment |
||||
*/ |
||||
public void setKeyComment(String key, String comment) |
||||
{ |
||||
keyComments.put(key, comment); |
||||
} |
||||
|
||||
|
||||
@SuppressWarnings("rawtypes") |
||||
@Override |
||||
public void store(OutputStream out, String comments) throws IOException |
||||
{ |
||||
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); |
||||
|
||||
final boolean escUnicode = false; |
||||
|
||||
if (comments != null) { |
||||
writeComments(bw, comments); |
||||
} |
||||
|
||||
synchronized (this) { |
||||
for (final Enumeration e = keys(); e.hasMoreElements();) { |
||||
boolean wasNewLine = false; |
||||
|
||||
String key = (String) e.nextElement(); |
||||
String val = (String) get(key); |
||||
key = saveConvert(key, true, escUnicode); |
||||
val = saveConvert(val, false, escUnicode); |
||||
|
||||
if (cfgSeparateSectionsByEmptyLine && !lastSectionBeginning.equals(key.split("[.]")[0])) { |
||||
if (!firstEntry) { |
||||
bw.newLine(); |
||||
bw.newLine(); |
||||
} |
||||
|
||||
wasNewLine = true; |
||||
lastSectionBeginning = key.split("[.]")[0]; |
||||
} |
||||
|
||||
if (keyComments.containsKey(key)) { |
||||
String cm = keyComments.get(key); |
||||
cm = cm.replace("\r", "\n"); |
||||
cm = cm.replace("\r\n", "\n"); |
||||
cm = cm.replace("\n\n", "\n \n"); |
||||
|
||||
final String[] cmlines = cm.split("\n"); |
||||
|
||||
if (!wasNewLine && !firstEntry && cfgEmptyLineBeforeComment) { |
||||
bw.newLine(); |
||||
} |
||||
for (final String cmline : cmlines) { |
||||
bw.write("# " + cmline); |
||||
bw.newLine(); |
||||
} |
||||
} |
||||
|
||||
bw.write(key + " = " + val); |
||||
bw.newLine(); |
||||
|
||||
firstEntry = false; |
||||
} |
||||
} |
||||
bw.flush(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Helper class which loads Properties from UTF-8 file (Properties use |
||||
* "ISO-8859-1" by default) |
||||
* |
||||
* @author Itay Maman |
||||
*/ |
||||
private static class PropertiesLoader { |
||||
|
||||
private static String escapifyStr(String str) |
||||
{ |
||||
final StringBuilder result = new StringBuilder(); |
||||
|
||||
final int len = str.length(); |
||||
for (int x = 0; x < len; x++) { |
||||
final char ch = str.charAt(x); |
||||
if (ch <= 0x007e) { |
||||
result.append(ch); |
||||
continue; |
||||
} |
||||
|
||||
result.append('\\'); |
||||
result.append('u'); |
||||
result.append(hexDigit(ch, 12)); |
||||
result.append(hexDigit(ch, 8)); |
||||
result.append(hexDigit(ch, 4)); |
||||
result.append(hexDigit(ch, 0)); |
||||
} |
||||
return result.toString(); |
||||
} |
||||
|
||||
|
||||
private static char hexDigit(char ch, int offset) |
||||
{ |
||||
final int val = (ch >> offset) & 0xF; |
||||
if (val <= 9) { |
||||
return (char) ('0' + val); |
||||
} |
||||
|
||||
return (char) ('A' + val - 10); |
||||
} |
||||
|
||||
|
||||
public static SortedProperties loadProperties(SortedProperties props, InputStream is) throws IOException |
||||
{ |
||||
return loadProperties(props, is, "utf-8"); |
||||
} |
||||
|
||||
|
||||
public static SortedProperties loadProperties(SortedProperties props, InputStream is, String encoding) throws IOException |
||||
{ |
||||
final StringBuilder sb = new StringBuilder(); |
||||
final InputStreamReader isr = new InputStreamReader(is, encoding); |
||||
while (true) { |
||||
final int temp = isr.read(); |
||||
if (temp < 0) { |
||||
break; |
||||
} |
||||
|
||||
final char c = (char) temp; |
||||
sb.append(c); |
||||
} |
||||
|
||||
final String read = sb.toString(); |
||||
|
||||
final String inputString = escapifyStr(read); |
||||
final byte[] bs = inputString.getBytes("ISO-8859-1"); |
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(bs); |
||||
|
||||
final SortedProperties ps = props; |
||||
ps.load(bais); |
||||
return ps; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Property entry in Property manager. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
private class Property { |
||||
|
||||
public String entryComment; |
||||
|
||||
public String name; |
||||
|
||||
public boolean bool = false; |
||||
public boolean defbool = false; |
||||
|
||||
public double num = -1; |
||||
public double defnum = -1; |
||||
|
||||
public String defstr = ""; |
||||
public String str = ""; |
||||
|
||||
public PropertyType type; |
||||
|
||||
|
||||
/** |
||||
* Property |
||||
* |
||||
* @param key key |
||||
* @param default_value default value |
||||
* @param entry_type type |
||||
* @param entry_comment entry comment |
||||
*/ |
||||
public Property(String key, boolean default_value, PropertyType entry_type, String entry_comment) { |
||||
name = key; |
||||
defbool = default_value; |
||||
type = entry_type; |
||||
entryComment = entry_comment; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Property entry |
||||
* |
||||
* @param key property key |
||||
* @param default_value default value |
||||
* @param entry_type property type from enum |
||||
* @param entry_comment property comment or null |
||||
*/ |
||||
public Property(String key, double default_value, PropertyType entry_type, String entry_comment) { |
||||
name = key; |
||||
defnum = default_value; |
||||
type = entry_type; |
||||
entryComment = entry_comment; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Property |
||||
* |
||||
* @param key key |
||||
* @param default_value default value |
||||
* @param entry_type type |
||||
* @param entry_comment entry comment |
||||
*/ |
||||
public Property(String key, String default_value, PropertyType entry_type, String entry_comment) { |
||||
name = key; |
||||
defstr = default_value; |
||||
type = entry_type; |
||||
entryComment = entry_comment; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get boolean |
||||
* |
||||
* @return the boolean |
||||
*/ |
||||
public boolean getBoolean() |
||||
{ |
||||
return bool; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get number |
||||
* |
||||
* @return the number |
||||
*/ |
||||
public int getInteger() |
||||
{ |
||||
return (int) Math.round(num); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get number as double |
||||
* |
||||
* @return the number |
||||
*/ |
||||
public double getDouble() |
||||
{ |
||||
return num; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get string |
||||
* |
||||
* @return the string |
||||
*/ |
||||
public String getString() |
||||
{ |
||||
return str; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Is this entry valid? |
||||
* |
||||
* @return is valid |
||||
*/ |
||||
public boolean isValid() |
||||
{ |
||||
switch (type) { |
||||
case STRING: |
||||
return str != null; |
||||
|
||||
case BOOLEAN: |
||||
case INT: |
||||
case DOUBLE: |
||||
return true; |
||||
|
||||
} |
||||
return false; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Load property value from a file |
||||
* |
||||
* @param string the string loaded |
||||
* @return was OK |
||||
*/ |
||||
public boolean parse(String string) |
||||
{ |
||||
switch (type) { |
||||
case INT: |
||||
|
||||
if (string == null) { |
||||
num = defnum; |
||||
return false; |
||||
} |
||||
|
||||
try { |
||||
num = Integer.parseInt(string.trim()); |
||||
} catch (final NumberFormatException e) { |
||||
num = defnum; |
||||
} |
||||
|
||||
break; |
||||
|
||||
case DOUBLE: |
||||
|
||||
if (string == null) { |
||||
num = defnum; |
||||
return false; |
||||
} |
||||
|
||||
try { |
||||
num = Double.parseDouble(string.trim()); |
||||
} catch (final NumberFormatException e) { |
||||
num = defnum; |
||||
} |
||||
|
||||
break; |
||||
|
||||
case STRING: |
||||
|
||||
if (string == null) { |
||||
str = defstr; |
||||
return false; |
||||
} |
||||
|
||||
str = string; |
||||
break; |
||||
|
||||
case BOOLEAN: |
||||
|
||||
if (string == null) { |
||||
bool = defbool; |
||||
return false; |
||||
} |
||||
|
||||
final String string2 = string.toLowerCase(); |
||||
bool = string2.equals("yes") || string2.equals("true") || string2.equals("on") || string2.equals("enabled") || string2.equals("enable"); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* prepare the contents for insertion into Properties |
||||
* |
||||
* @return the string prepared, or null if type is invalid |
||||
*/ |
||||
@Override |
||||
public String toString() |
||||
{ |
||||
if (!isValid()) { |
||||
if (type == PropertyType.INT || type == PropertyType.DOUBLE) { |
||||
num = defnum; |
||||
} |
||||
} |
||||
|
||||
switch (type) { |
||||
case INT: |
||||
return Integer.toString((int) num); |
||||
|
||||
case DOUBLE: |
||||
return Calc.floatToString((float) num); |
||||
|
||||
case STRING: |
||||
return str; |
||||
|
||||
case BOOLEAN: |
||||
return bool ? "True" : "False"; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* If this entry is not valid, change it to the dafault value. |
||||
*/ |
||||
public void validate() |
||||
{ |
||||
if (!isValid()) { |
||||
if (type == PropertyType.STRING) { |
||||
str = defstr; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Property types |
||||
*/ |
||||
private enum PropertyType |
||||
{ |
||||
BOOLEAN, INT, STRING, DOUBLE; |
||||
} |
||||
|
||||
/** put newline before entry comments */ |
||||
private boolean cfgNewlineBeforeComments = true; |
||||
/** Disable entry validation */ |
||||
private boolean cfgNoValidate = true; |
||||
/** Put newline between sections. */ |
||||
private boolean cfgSeparateSections = true; |
||||
/** Force save, even if nothing changed (used to save changed comments) */ |
||||
private boolean cfgForceSave; |
||||
|
||||
private final File file; |
||||
private String fileComment = ""; |
||||
|
||||
private final TreeMap<String, Property> entries; |
||||
private final TreeMap<String, String> keyRename; |
||||
private final TreeMap<String, String> setValues; |
||||
private SortedProperties pr = new SortedProperties(); |
||||
|
||||
|
||||
/** |
||||
* Create property manager from file path and an initial comment. |
||||
* |
||||
* @param file file with the props |
||||
* @param comment the initial comment. Use \n in it if you want. |
||||
*/ |
||||
public PropertyManager(File file, String comment) { |
||||
this.file = file; |
||||
this.entries = new TreeMap<String, Property>(); |
||||
this.setValues = new TreeMap<String, String>(); |
||||
this.keyRename = new TreeMap<String, String>(); |
||||
this.fileComment = comment; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Load, fix and write to file. |
||||
*/ |
||||
public void apply() |
||||
{ |
||||
boolean needsSave = false; |
||||
FileInputStream fis = null; |
||||
try { |
||||
new File(file.getParent()).mkdirs(); |
||||
fis = new FileInputStream(file); |
||||
pr = PropertiesLoader.loadProperties(pr, fis); |
||||
|
||||
} catch (final IOException e) { |
||||
needsSave = true; |
||||
pr = new SortedProperties(); |
||||
} finally { |
||||
try { |
||||
if (fis != null) fis.close(); |
||||
} catch (final IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
pr.cfgSeparateSectionsByEmptyLine = cfgSeparateSections; |
||||
pr.cfgEmptyLineBeforeComment = cfgNewlineBeforeComments; |
||||
|
||||
final ArrayList<String> keyList = new ArrayList<String>(); |
||||
|
||||
// rename keys
|
||||
for (final Entry<String, String> entry : keyRename.entrySet()) { |
||||
if (pr.getProperty(entry.getKey()) == null) { |
||||
continue; |
||||
} |
||||
pr.setProperty(entry.getValue(), pr.getProperty(entry.getKey())); |
||||
pr.remove(entry.getKey()); |
||||
needsSave = true; |
||||
} |
||||
|
||||
// set the override values into the freshly loaded properties file
|
||||
for (final Entry<String, String> entry : setValues.entrySet()) { |
||||
pr.setProperty(entry.getKey(), entry.getValue()); |
||||
needsSave = true; |
||||
} |
||||
|
||||
// validate entries one by one, replace with default when needed
|
||||
for (final Property entry : entries.values()) { |
||||
keyList.add(entry.name); |
||||
|
||||
final String propOrig = pr.getProperty(entry.name); |
||||
if (!entry.parse(propOrig)) needsSave = true; |
||||
if (!cfgNoValidate) { |
||||
entry.validate(); |
||||
} |
||||
|
||||
if (entry.entryComment != null) { |
||||
pr.setKeyComment(entry.name, entry.entryComment); |
||||
} |
||||
|
||||
if (propOrig == null || !entry.toString().equals(propOrig)) { |
||||
pr.setProperty(entry.name, entry.toString()); |
||||
|
||||
needsSave = true; |
||||
} |
||||
} |
||||
|
||||
// removed unused props
|
||||
for (final String propname : pr.keySet().toArray(new String[pr.size()])) { |
||||
if (!keyList.contains(propname)) { |
||||
pr.remove(propname); |
||||
needsSave = true; |
||||
} |
||||
|
||||
} |
||||
|
||||
// save if needed
|
||||
if (needsSave || cfgForceSave) { |
||||
try { |
||||
pr.store(new FileOutputStream(file), fileComment); |
||||
} catch (final IOException ioe) { |
||||
ioe.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
setValues.clear(); |
||||
keyRename.clear(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param newlineBeforeComments put newline before comments |
||||
*/ |
||||
public void cfgNewlineBeforeComments(boolean newlineBeforeComments) |
||||
{ |
||||
this.cfgNewlineBeforeComments = newlineBeforeComments; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param separateSections do separate sections by newline |
||||
*/ |
||||
public void cfgSeparateSections(boolean separateSections) |
||||
{ |
||||
this.cfgSeparateSections = separateSections; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param forceSave save even if unchanged. |
||||
*/ |
||||
public void cfgForceSave(boolean forceSave) |
||||
{ |
||||
this.cfgForceSave = forceSave; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param validate enable validation |
||||
*/ |
||||
public void enableValidation(boolean validate) |
||||
{ |
||||
this.cfgNoValidate = !validate; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get a property entry (rarely used) |
||||
* |
||||
* @param n key |
||||
* @return the entry |
||||
*/ |
||||
private Property get(String n) |
||||
{ |
||||
try { |
||||
return entries.get(n); |
||||
} catch (final Throwable t) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get boolean property |
||||
* |
||||
* @param n key |
||||
* @return the boolean found, or false |
||||
*/ |
||||
public Boolean getBoolean(String n) |
||||
{ |
||||
try { |
||||
return entries.get(n).getBoolean(); |
||||
} catch (final Throwable t) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get numeric property |
||||
* |
||||
* @param n key |
||||
* @return the int found, or null |
||||
*/ |
||||
public Integer getInteger(String n) |
||||
{ |
||||
try { |
||||
return get(n).getInteger(); |
||||
} catch (final Throwable t) { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get numeric property as double |
||||
* |
||||
* @param n key |
||||
* @return the double found, or null |
||||
*/ |
||||
public Double getDouble(String n) |
||||
{ |
||||
try { |
||||
return get(n).getDouble(); |
||||
} catch (final Throwable t) { |
||||
return -1D; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get string property |
||||
* |
||||
* @param n key |
||||
* @return the string found, or null |
||||
*/ |
||||
public String getString(String n) |
||||
{ |
||||
try { |
||||
return get(n).getString(); |
||||
} catch (final Throwable t) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a boolean property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
*/ |
||||
public void putBoolean(String n, boolean d) |
||||
{ |
||||
entries.put(n, new Property(n, d, PropertyType.BOOLEAN, null)); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a boolean property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putBoolean(String n, boolean d, String comment) |
||||
{ |
||||
entries.put(n, new Property(n, d, PropertyType.BOOLEAN, comment)); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a numeric property (double) |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
*/ |
||||
public void putDouble(String n, int d) |
||||
{ |
||||
entries.put(n, new Property(n, d, PropertyType.DOUBLE, null)); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a numeric property (double) |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putDouble(String n, int d, String comment) |
||||
{ |
||||
entries.put(n, new Property(n, d, PropertyType.DOUBLE, comment)); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a numeric property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
*/ |
||||
public void putInteger(String n, int d) |
||||
{ |
||||
entries.put(n, new Property(n, d, PropertyType.INT, null)); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a numeric property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putInteger(String n, int d, String comment) |
||||
{ |
||||
entries.put(n, new Property(n, d, PropertyType.INT, comment)); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a string property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
*/ |
||||
public void putString(String n, String d) |
||||
{ |
||||
entries.put(n, new Property(n, d, PropertyType.STRING, null)); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a string property |
||||
* |
||||
* @param n key |
||||
* @param d default value |
||||
* @param comment the in-file comment |
||||
*/ |
||||
public void putString(String n, String d, String comment) |
||||
{ |
||||
entries.put(n, new Property(n, d, PropertyType.STRING, comment)); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Rename key before doing "apply"; value is preserved |
||||
* |
||||
* @param oldKey old key |
||||
* @param newKey new key |
||||
*/ |
||||
public void renameKey(String oldKey, String newKey) |
||||
{ |
||||
keyRename.put(oldKey, newKey); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Set value saved to certain key; use to save runtime-changed configuration |
||||
* values. |
||||
* |
||||
* @param key key |
||||
* @param value the saved value |
||||
*/ |
||||
public void setValue(String key, Object value) |
||||
{ |
||||
setValues.put(key, value.toString()); |
||||
return; |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue