Skip to content

Instantly share code, notes, and snippets.

@Xyene
Created October 23, 2012 22:59
Show Gist options
  • Save Xyene/3942326 to your computer and use it in GitHub Desktop.
Save Xyene/3942326 to your computer and use it in GitHub Desktop.
Even easier config files, with comments!
/**
* A class for saving/loading lazy configuration classes/files.
* Based on codename_B's non static config 'offering' :)
* Inspired by md_5's easy config
*
* Node commenting by Xiaomao, fixed by Icyene
* Integer limiting by Icynene
*/
public class ReflectConfiguration {
private final Plugin plugin;
private final String name;
private final String prefix;
private final String header;
/**
* Creates a ReflectConfiguration file based on given name
*
* @param plugin The plugin
* @param name The name of the file to write to
*/
public ReflectConfiguration(Plugin plugin, String name) {
this.plugin = plugin;
this.name = name;
this.prefix = plugin.getName();
this.header = prefix + " configuration file: '" + name + "'.\nGenerated for " + prefix + " version " + plugin.getDescription().getVersion() + ".";
}
/**
* Loads the object.
*/
public void load() {
try {
synchronized (this) {
plugin.getLogger().log(Level.INFO, "Loading configuration file: " + name);
onLoad(plugin);
}
} catch (Exception e) {
ErrorLogger.generateErrorLog(e);
}
}
private void onLoad(Plugin plugin) throws Exception {
synchronized (this) {
File worldFolder = new File(plugin.getDataFolder() + File.separator + "worlds");
if (!worldFolder.exists()) {
if (!worldFolder.mkdir()) {
ErrorLogger.generateErrorLog(new RuntimeException("Failed to create configuration directory!"));
}
}
File worldFile = new File(worldFolder.getAbsoluteFile(), File.separator + name + ".yml");
YamlConfiguration worlds = YamlConfiguration.loadConfiguration(worldFile);
((FileConfiguration) worlds).options().header(header);
for (Field field : getClass().getDeclaredFields()) {
if (doSkip(field))
continue;
String path = prefix + "." + field.getName().replaceAll("__", " ").replaceAll("_", ".");
if (worlds.isSet(path)) {
LimitInteger lim;
if ((lim = field.getAnnotation(LimitInteger.class)) != null) {
int limit = lim.limit();
boolean doCorrect = false;
try {
if (worlds.getInt(path) > limit) {
doCorrect = true;
}
} catch (Exception e) {
doCorrect = true;
}
if (doCorrect) {
plugin.getLogger().log(Level.SEVERE, lim.warning().replace("%node", "'" + path.substring(6) + "'").replace("%limit", limit + ""));
if (lim.correct())
worlds.set(path, lim.limit());
}
}
field.set(this, worlds.get(path));
} else
worlds.set(path, field.get(this));
}
worlds.save(worldFile);
Files.write(StringUtils.join(addComments(Files.toString(worldFile, Charset.defaultCharset()).split("\n")), "\n"), worldFile, Charset.defaultCharset());
}
}
Collection<String> addComments(String[] lines) {
int prevlevel = 0;
final int indent = 2;
LinkedList<String> outlines = new LinkedList<String>();
Stack<String> hierarchy = new Stack<String>();
for (String line : lines) {
String content = StringUtils.stripStart(line, " ");
int spaces = line.length() - content.length(),
level = spaces / indent + 1;
String[] tokens = content.split(":", 2);
String name = tokens[0];
if (level <= prevlevel) {
for (int i = 0; i <= prevlevel - level; ++i) {
hierarchy.pop();
}
}
hierarchy.push(name);
prevlevel = level;
String id = StringUtils.join(hierarchy, "_").replaceAll(" ", "__");
Comment comment = null;
try {
comment = getClass().getDeclaredField(id.replaceAll(prefix + ".", "")).getAnnotation(Comment.class);
} catch (NoSuchFieldException ignored) {
}
if (comment == null) {
outlines.add(line);
continue;
}
String indentPrefix = StringUtils.repeat(" ", spaces);
if (comment.location() == Comment.CommentLocation.TOP)
for (String data : comment._())
outlines.add(indentPrefix + "# " + data);
if (comment.location() == Comment.CommentLocation.INLINE) {
String[] comments = comment._();
outlines.add(line + " # " + comments[0]);
for (int i = 1; i < comments.length; ++i)
outlines.add(StringUtils.repeat(" ", line.length() + 1) + "# " + comments[i]);
} else
outlines.add(line);
if (comment.location() == Comment.CommentLocation.BOTTOM)
for (String data : comment._())
outlines.add(indentPrefix + "# " + data);
}
return outlines;
}
public boolean doSkip(Field field) {
int mod = field.getModifiers();
return Modifier.isFinal(mod) || Modifier.isTransient(mod) || Modifier.isVolatile(mod);
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LimitInteger {
int limit() default 100;
String warning() default "%node cannot be over %limit! Defaulted to value of %limit.";
boolean correct() default true;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Comment {
String[] _();
CommentLocation location() default CommentLocation.INLINE;
public enum CommentLocation {
INLINE(1),
TOP(2),
BOTTOM(3);
CommentLocation(int location) {
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment