Configuration API Reference/ko

The Configuration API is a set of tools to help developers quickly parse and emit configuration files that are human readable and editable. Despite the name, the API can easily be used to store plugin data in addition to plugin configuration. Presently only YAML configurations can be used. The API however was designed to be extensible and allow for other implementations.

The Configuration API can be found in the org.bukkit.configuration and org.bukkit.configuration.file packages. Plugins that were created before version 1.1-R5 may have used an older and different implmention that resided in org.bukkit.util.configuration. These implementations are not compatible and the old package has since been removed.

This introduction assumes that you have some knowledge about proper object oriented design, Java, and the core design of Bukkit plugins. This page is not a substitute for the JavaDocs for the FileConfiguration Class

## 기본 항목

### 설정 오브젝트

당신이 만들 플러그인은 JavaPlugin 을 상속받기때문에, JavaPlugin 의 메소드와 필드를 상속받게됩니다. 상속된 메소드는 *getConfig()* 오브젝트의 형식인 FileConfiguration 을 반환하게됩니다. 이 오브젝트는 당신의 플러그인 데이터폴더 안에 있는 *config.yml* 에 입력 또는 수정됩니다.

처음에 *getConfig()* 이 당신의 플러그인에 호출되는데, *config.yml* 이 디스크에서 로드되며, 기존 값들이 플러그인 jar 파일에서 로드됩니다. *getConfig()* 이 호출되면 *FileConfiguration* 이라는 메모리에 있는 오브젝트를 리턴할것입니다. 작업이 수행되는 동안,saveConfig() 메소드를 사용하지 않으면 시스템은 해당 콘피그 파일을 파일에 저자하지 않습니다. 마찬가지로,FileConfiguration은 자동 저장을 지원하지 않기 때문에 저장 메소드를 넣어주지 않으면 파일에 반영되지 않습니다. 만약 *config.yml* 파일이 당신의 데이터 폴더에 존재하지 않는다면,빈 *config.yml* 파일이 데이터 폴더에 생성되고, 시스템이 자동으로 빈 *FileConfiguration* 을 불러옵니다..

 **Warning**: 만약 당신이 반환된 객체에서 *getConfig()* 를 할당할 경우, 반드시 static 제한자를 사용하면 안됩니다.
  **Warning**: 만약 해당 작업을 반드시 해야할경우, *getConfig()* 를 reloadConfig 이후에 재 선언해야 합니다.

 **Note**: 이 방법은 instance를 사용하는것보다 *getConfig()* 를 사용하기에 쉬울 수도 있습니다.
### 경로

콘피그 파일은 *키*라는 경로의 조직입니다.각각의 데이터는 ConfigurationSection 혹은 경로에 String 혹은 List형식으로 존재합니다. *getKeys(boolean)* 메소드는 시스템에 로드된 *FileConfigurationSection*의 경로의 집합을 반환합니다. 불 대수의 값은 반환된 값이 재귀 호출을 사용할지의 여부를 선택합니다. 만약 true라면 해당 메소드는 상위 경로와 하위 경로까지 모두 반환합니다. 만약 false라면 주어진 구역의 경로만 반환합니다. 특별한 구간의 경로를 얻으려면, *getKeys(boolean)* 메소드를 해당 구역에서 반드시 호출해야합니다. 어떠한 특정 구역을 호출하려면 *getConfigurationSection("문자열(경로)")*를 사용해 호출하세요..

 **Note**: getKey 메소드는 Set 과 같은 문자열을 반환합니다.
### Paths

콘피그 API는 그들을 구별하기 위해 개별적인 문자열 형식의 키(경로)를 가집니다. 경로(키)들은 콘피그의 값을 구분하기 위해 쓰입니다. 각 수준은 기본적인 경로 구분자 작은 따음표('경로명')으로 구별됩니다.다음은 YAML 콘피그 파일의 예제입니다.

>
> ```
> 경로: 값
> 경로1:
>  세부경로1: 값
>  세부경로2:
>  - 값
>  - 값
>  - 값
>  세부경로3
>  세부경로4: 값
>  \*:
>  경로2: value
>  경로3: value
>
> ```
>

* 경로
* 경로1
* 경로1.세부경로1
* 경로1.세부경로2
* 경로1.세부경로3
* 경로1.세부경로3.세부경로4
* 경로1.\*
* 경로1.\*.경로2
* 경로1.\*.경로3

### 기본 값

A default *config.yml* should be provided in your jar for users. In the event that a config.yml is missing or incomplete, values will be loaded from included *config.yml*. The provided file must be named *config.yml* and be placed in the same directory as your plugin.yml. The file should have the intended structure of your *config.yml*. This file can be copied as is into the datafolder by invoking saveDefaultConfig() on the Appropriate instance of JavaPlugin.

>
> ```
> this.saveDefaultConfig()
>
> ```
>

If dynamic key-value pairs are required as default values, they can added as defaults to the configuration with invocations of *addDefault(String, Object)* and *addDefaults(Map<String,Object>)* methods.

In certain cases if you wish to append new key-value pairs to an existing config.yml you can set the copyDefaults to true for the ConfigurationOptions object.

>
> ```
> this.getConfig().options().copyDefaults(true)
>
> ```
>

#### config.yml의 복사본 만들기

당신은 JavaPlugin의 saveDefaultConfig() 메소드를 호출하여 플러그인의 데이터 폴더 내부의 "jar 파일 안에 있는  config.yml 파일"의 복사본을 만들 수 있습니다. saveDefaultConfig()는 기존 파일을 덮어 쓰지 않습니다.

### 값 가져오기

경로에서 값을 가져오는 메소드는 많이 존재합니다. 다음 경로에서 목록을 확인 할 수 있습니다: here. 모든 메소드는 경로를 통해 값을 반환합니다. 다음은 일반적으로 사용하는 값 반환 메소드입니다.

* getBoolean("경로(키)") // Boolean 을 반환합니다.
* getInt("경로(키)") // Int 를 반환합니다.
* getString("경로(키)") // String을 반환합니다.
* getList("경로(키)") // List를 반환합니다.
* getStringList("경로(키)") // List<String>을 반환합니다.

#### 해쉬맵

해쉬맵같은 경우에는,다른 데이터 처리 형식과 많이 달라집니다. 맵 형식의 데이터에는 제한이 존재합니다. 반드시 키를 문자열로 사용해야 하고,값은 원시적인 데이터 혹은 문자열,리스트,맵 혹은 ConfigurationSerializable 타입만 사용이 가능합니다. 그들은 그들의 형식을 잃은 채로 저장됩니다.

*HashMap*을 가져오려면, 먼저 *ConfigurationSection* 검색이 가능해야합니다. 당신은 데이터 반환을 getConfigurationSection을 사용해 할 수 있습니다. The getValues method will return the values in the ConfigurationSection as a map, it takes a boolean which controls if the nested maps will be returned in the map. You can obtain the original map by invoking getValues(false) on the returned ConfigurationSection. Due to the way Java handles generic classes, type information will be lost, thus a cast will need to be performed to set the original type information. The API makes no guarantees that the cast you perform will be safe.

>
> ```
> this.getConfig().getConfigurationSection("path.to.map").getValues(false)
>
> ```
>

### 값 설정하기

Writing values involves invoking the *set(String, Object)* method on an instance of Configuration. Unlike the different get methods that *FileConfiguration* has, there is only one set method. Not all objects can be set, only primitive types, *String*, *Lists*, and types that implement *ConfigurationSerializable*, such as *Vector* and *ItemStack*, can be set. To erase a value supply null as a parameter. All changes made by set will only affect the copy of the configuration in memory, and will not persist beyond restarting the server until the configuration is saved. Following are some example uses:

>
> ```
> // setting a boolean value
> this.getConfig().set("path.to.boolean", true);
>
> // setting a String
> String stringValue = "Hello World!";
> this.getConfig().set("path.to.string", stringValue);
>
> // setting an int value
> int integerValue = 8;
> this.getConfig().set("path.to.integer", integerValue);
>
> // Setting a List of Strings
> // The List of Strings is first defined in this array
> List<String> listOfStrings = Arrays.asList("Hello World", "Welcome to Bukkit", "Have a Good Day!");
> this.getConfig().set("path.to.list", listOfStrings);
>
> // Setting a vector
> // event is assumed to be an existing event inside an "onEvent" method.
> Vector vector = event.getPlayer().getLocation().toVector();
> this.getConfig().set("path.to.vector", vector);
>
> // Erasing a value
> this.getConfig().set("path.to.value", null);
>
> ```
>

#### HashMaps

When HashMaps are used as a value, they are treated slightly differently. The Map must parameterized with a String type for the key, and the value must be parameterized as a boxed primitive, String, List, Map, or a ConfigurationSerializable.

While you can use the set method to directly set a HashMap to a key, you cannot directly retrieve the Map back with the get method after reading directly from disk. The context above is to minimize unpredictability.

To set a *HashMap*, a *ConfigurationSection* must be created for that HashMap. You can only set HashMap where the key is a string the the value is something that is ConfigurationSerializable. The createSectionMethod

>
> ```
> this.getConfig().createSection(String path, Map< String, Object > map)
>
> ```
>

### 파일 저장하기

If make any changes to the*FileConfiguration* with set methods, or mutate any *Lists*, you will need to save the changes to disk if you wish to keep these changes after the plugin is disabled. To save the file to disk invoke the saveConfig method for your plugin, it will overwrite the file already there.

>
> ```
> this.saveConfig();
>
> ```
>

### 디스크에서 다시 읽어오기

If you suspect that users have made changes to the *config.yml* in the data folder, those changes are not reflected in memory. Invoke the *reloadConfig()* method of your plugin to load from the disk again. It will destroy all changes in memory.

>
> ```
> this.reloadConfig();
>
> ```
>

## 고급 항목

The following are some more advanced topics, meant for more advanced plugins. If you only require the default *config.yml*, creating custom methods for reading, and saving, you will not need to go this far.

### Options

Every *FileConfiguration* instance is associated with a FileConfigurationOptions object. The *FileConfigurationOptions* object controls the behavior of the *FileConfiguration* it is associated with. *FileConfiguration'*s *options()* method returns the *FileConfigurationOption's* responsible for it. With it you can check and set each option. There are currently four options. Be aware that the methods are overloaded, for example *copyDefaults()* which returns a boolean and *copyDefaults(boolean)* which returns it self, but has a side effect which changes the state.

#### CopyDefaults

The *copyDefaults* option changes the behavior of Configuration's save method. By default, the defaults of the configuration will not be written to the target save file. If set to true, it will write out the default values, to the target file. However, once written, you will not be able to tell the difference between a default and a value from the configuration.

#### PathSeperator

PathSeperator changes the character that is used to separate the different levels of the configuration. By default it is the "." (period) but it can be changed to any char.

#### Header

Header is the comment block at the top of a YAML file, it is applied to the save output. The header is the only comment that Configuration API knows how to copy.

#### copyHeader

If *copyHeader()* returns true then the header will be copied on save, from the default source.

### Arbitrary Configurations

If you require additional YAML files, for storing configuration information or persisting additional game information you will need to write your own methods for accessing the additional configuration files. Modeled after JavaPlugin getConfig, reloadConfig, saveConfig methods, the following is an example how to write your own methods to read and save to custom configuration files. Since these config files belong to your plugin, you can put this method in your main class so that you can have the same access as you have with config.yml. You will have to write a set of these methods for each YAML file. The advantage here, is that you can use each set in the same manner as the provided methods for the default config.yml. Alternately, adding additional methods can keep the method count lower and allow access to multiple files.

#### Mirroring the JavaPlugin implementation

JavaPlugin implements methods for config.yml. A plugin needs to implement its own methods to access configuration files unique to the plugin. After implementing the methods for the plugin, they can be invoked in the same context as the inherited *getConfig()*, *reloadConfig()*, *saveConfig()*, and "saveDefaultConfig()" methods from JavaPlugin. The following can be made into a single class which allows access to any yaml file. Such a class can be found here

First you will need to declare two fields and initialize them to null for each of the custom configuration files. One to hold the *FileConfiguration* object and one to hold the *File* object. The File object represents the file on the disk, and the FileConfiguration represents the contents of the configuration.

>
> ```
> private FileConfiguration customConfig = null;
> private File customConfigFile = null;
>
> ```
>

##### Implementation for Reloading

Then, write the method that is responsible for loading the config from disk. It will load the file, and search the jar for a default customConfig.yml.

>
> ```
> public void reloadCustomConfig() {
>  if (customConfigFile == null) {
>  customConfigFile = new File(getDataFolder(), "customConfig.yml");
>  }
>  customConfig = YamlConfiguration.loadConfiguration(customConfigFile);
>
>  // Look for defaults in the jar
>  InputStream defConfigStream = this.getResource("customConfig.yml");
>  if (defConfigStream != null) {
>  YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
>  customConfig.setDefaults(defConfig);
>  }
> }
>
> ```
>

##### Implementation for Getting

Next, you need to write the getter method. Check if *customConfig* is null, if it is load from disk.

>
> ```
> public FileConfiguration getCustomConfig() {
>  if (customConfig == null) {
>  this.reloadCustomConfig();
>  }
>  return customConfig;
> }
>
> ```
>

##### Implementation for Saving

Finally, write the save method, which saves changes and overwrites the file on disk.

>
> ```
> public void saveCustomConfig() {
>  if (customConfig == null || customConfigFile == null) {
>  return;
>  }
>  try {
>  getCustomConfig().save(customConfigFile);
>  } catch (IOException ex) {
>  this.getLogger().log(Level.SEVERE, "Could not save config to " + customConfigFile, ex);
>  }
> }
>
> ```
>

##### Implementation for Defaults

Optionally, you may want to write a method that mimics JavaPlugin's saveDefaultConfig() method.

>
> ```
> public void saveDefaultConfig() {
>  if (customConfigFile == null) {
>  customConfigFile = new File(getDataFolder(), "customConfig.yml");
>  }
>  if (!configFile.exists()) {
>  this.plugin.saveResource(fileName, false);
>  }
> }
>
> ```
>

### Serializing and Deserializing Objects

The Configuration API, as mentioned above can store Java objects that implement the *ConfigurationSerializable* Interface. Object serialization facilitates easy saving and loading so plugin authors can focus on other parts of their plugin. It greatly simplifies tasks such as storing a *Location* in YAML, a developer can serialize a wrapper class, which provide methods to retrieve a *Location*.

Classes, in addition to implementing the *ConfigurationSerializable* interface must also implment one of the following as noted in the Javadoc, so that they can be serialized by the API:

* A constructor that accepts a single *Map*.
* A static method "deserialize" that accepts a single *Map* and returns the class.
* A static method "valueOf" that accepts a single Map and returns the class.

In order for a serialized object to be deserialized, it must also be registered with ConfigurationSerilization. The static registerClass method must be invoked once per class that has been serialized.

This statement can be placed in a static initializer block in your main class.

>
> ```
> ConfigurationSerialization.registerClass(Class<? extends ConfigurationSerializable>)
>
> ```
>

#### Aliases

When classes are serialized they are marked with their fully qualified name.

You can provide an alias to your class so that it does not serialize with the fully qualified name of your class, but the alias instead. You provide the alias with the *SerializableAs* annotation to the class implementing *ConfigurationSerializable*.

```
@SerializableAs(String)

```
 When registering a class with an alias, the alias must be provided on registration.

>
> ```
> ConfigurationSerialization.registerClass(Class<? extends ConfigurationSerializable>, String)
>
> ```
>

예제
--

Below is the an example plugin that uses the new Configuration API to be display messages as an MOTD as players join, and for the player to retrieve the rules on command. It does not follow proper style and plugin layout to keep the number of lines to a minimum.

>
> ```
> import java.util.\*;
> import org.bukkit.command.\*;
> import org.bukkit.event.\*;
> import org.bukkit.plugin.java.JavaPlugin;
> import org.bukkit.configuration.file.FileConfiguration;
>
>
> public class SimpleMOTD extends JavaPlugin {
>
>  @Override
>  public void onEnable() {
>  // Save a copy of the default config.yml if one is not there
>  this.saveDefaultConfig();
>
>  // Register a new listener
>  getServer().getPluginManager().registerEvents(new Listener() {
>
>  @EventHandler
>  public playerJoin(PlayerJoinEvent event) {
>  // On player join send them the message from config.yml
>  event.getPlayer().sendMessage(SimpleMOTD.this.getConfig().getString("message"));
>  }
>  }, this);
>
>  // Set the command executor for the rules command
>  this.getCommand("rules").setExecutor(new CommandExecutor() {
>
>  public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
>  // On command send the rules from config.yml to the sender of the command
>  List<String> rules = SimpleMOTD.this.getConfig().getStringList("rules");
>  for (String s : rules)
>  sender.sendMessage(s);
>  }
>  return true;
>  }
>  });
>  }
> }
>
> ```
>

 플러그인의 jar 안에 있는 config.yml 의 기본값.

```
# default config.yml
message: Hello World and Welcome! :)
rules:
 - Play Nice
 - Respect others
 - Have Fun

```