/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package pluginbase.bukkit.properties;
import pluginbase.logging.Logging;
import pluginbase.logging.PluginLogger;
import pluginbase.messages.PluginBaseException;
import pluginbase.properties.Properties;
import org.bukkit.configuration.InvalidConfigurationException;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* Optionally commented Yaml implementation of Properties.
* <p/>
* <b>Do note:</b> Using comments will cause disk writes to take significantly longer than not using them.
* <p/>
* See {@link pluginbase.bukkit.properties.YamlProperties.Loader} for creating a YamlProperties object.
*/
public class YamlProperties extends AbstractFileProperties implements Properties {
private final File configFile;
private final boolean doComments;
private final boolean autoDefaults;
/**
* Constructs a new YamlProperties object with the specified parameters.
*
* @param logger a logger to use for any important messages this Properties object may need to log.
* @param doComments true to use comments.
* @param autoDefaults true to set default values automatically.
* @param configFile the file to load config from and to write config to.
* @param configClasses the classes containing the Property objects associated with this Properties object.
* @throws PluginBaseException if anything goes wrong while loading/writing-to the file.
*/
protected YamlProperties(@NotNull final PluginLogger logger, boolean doComments, boolean autoDefaults,
@NotNull final File configFile, @NotNull final Class... configClasses) throws PluginBaseException {
super(logger, CommentedYamlConfiguration.loadCommentedConfiguration(configFile, doComments), configClasses);
this.configFile = configFile;
this.doComments = doComments;
this.autoDefaults = autoDefaults;
// Prepare the loaded configuration file.
prepareConfig();
// Saves the configuration from memory to file.
flush();
}
/**
* A helper class used to load new YamlProperties objects from a file with the right options.
*/
public static class Loader {
private final PluginLogger logger;
private final File configFile;
private final Class[] configClasses;
private boolean doComments = true;
private boolean autoDefaults = true;
/**
* Creates a new datasource for a YamlProperties object.
* <p/>
* By default, the loaded YamlProperties will have comments and automatically set defaults.
* Use the optional methods in this class to change these options.
* <p/>
* Use {@link #load()} to finalize the options and create the YamlProperties object.
*
* @param logger a logger to use for any important messages this Properties object may need to log.
* @param configFile the file to use for the Configuration object.
* @param configClasses the classes the YamlProperties will get its Property objects from.
*/
public Loader(@NotNull final PluginLogger logger,
@NotNull final File configFile,
@NotNull final Class... configClasses) {
this.logger = logger;
this.configFile = configFile;
this.configClasses = configClasses;
}
/**
* Specifies whether ot not to use comments on the YamlProperties object.
* <p/>
* <b>default:</b> true
*
* @param doComments true to use comments.
* @return this Loader to chain methods.
*/
public Loader comments(final boolean doComments) {
this.doComments = doComments;
return this;
}
/**
* Specifies whether ot not to automatically default values on the YamlProperties object.
* <p/>
* <b>default:</b> true
*
* @param autoDefaults true to use automatically default Property values.
* @return this Loader to chain methods.
*/
public Loader defaults(final boolean autoDefaults) {
this.autoDefaults = autoDefaults;
return this;
}
/**
* Loads a new YamlProperties object with all the specified options.
*
* @return a new YamlProperties object with all the specified options.
* @throws PluginBaseException if anything goes wrong while loading the file.
*/
public YamlProperties load() throws PluginBaseException {
return new YamlProperties(logger, doComments, autoDefaults, configFile, configClasses);
}
}
private void prepareConfig() {
deserializeAll();
// Sets defaults config values
if (autoDefaults) {
this.setDefaults();
}
config.options().header(getHeader());
}
private void loadConfig() throws PluginBaseException {
try {
config.load(configFile);
} catch (FileNotFoundException e) {
throw new PluginBaseException(e);
} catch (IOException e) {
throw new PluginBaseException(e);
} catch (InvalidConfigurationException e) {
throw new PluginBaseException(e);
}
}
/** {@inheritDoc} */
@Override
public void reload() throws PluginBaseException {
loadConfig();
prepareConfig();
}
/** {@inheritDoc} */
@Override
public void flush() throws PluginBaseException {
CommentedYamlConfiguration newConfig;
try {
newConfig = new EncodedYamlConfiguration("UTF-8", doComments);
} catch (UnsupportedEncodingException e) {
Logging.warning("Could not create UTF-8 configuration. Special/Foreign characters may not be saved.");
newConfig = new CommentedYamlConfiguration(doComments);
}
newConfig.options().header(getHeader());
serializeAll(newConfig);
if (doComments) {
doComments(newConfig);
}
try {
newConfig.save(configFile);
} catch (IOException e) {
throw new PluginBaseException(e);
}
}
@NotNull
protected String getHeader() {
return "";
}
}