001/* 002 * Configurate 003 * Copyright (C) zml and Configurate contributors 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package ninja.leaping.configurate.yaml; 018 019import ninja.leaping.configurate.ConfigurationNode; 020import ninja.leaping.configurate.ConfigurationOptions; 021import ninja.leaping.configurate.loader.AbstractConfigurationLoader; 022import ninja.leaping.configurate.loader.CommentHandler; 023import ninja.leaping.configurate.loader.CommentHandlers; 024import org.checkerframework.checker.nullness.qual.NonNull; 025import org.yaml.snakeyaml.DumperOptions; 026import org.yaml.snakeyaml.DumperOptions.FlowStyle; 027import org.yaml.snakeyaml.Yaml; 028 029import java.io.BufferedReader; 030import java.io.IOException; 031import java.io.Writer; 032 033/** 034 * A loader for YAML-formatted configurations, using the SnakeYAML library for parsing and generation. 035 * 036 */ 037public class YAMLConfigurationLoader extends AbstractConfigurationLoader<ConfigurationNode> { 038 039 /** 040 * Creates a new {@link YAMLConfigurationLoader} builder. 041 * 042 * @return A new builder 043 */ 044 @NonNull 045 public static Builder builder() { 046 return new Builder(); 047 } 048 049 /** 050 * Builds a {@link YAMLConfigurationLoader}. 051 */ 052 public static class Builder extends AbstractConfigurationLoader.Builder<Builder> { 053 private final DumperOptions options = new DumperOptions(); 054 055 protected Builder() { 056 setIndent(4); 057 } 058 059 /** 060 * Sets the level of indentation the resultant loader should use. 061 * 062 * @param indent The indent level 063 * @return This builder (for chaining) 064 */ 065 @NonNull 066 public Builder setIndent(int indent) { 067 options.setIndent(indent); 068 return this; 069 } 070 071 /** 072 * Gets the level of indentation to be used by the resultant loader. 073 * 074 * @return The indent level 075 */ 076 public int getIndent() { 077 return options.getIndent(); 078 } 079 080 /** 081 * Sets the flow style the resultant loader should use. 082 * 083 * Flow: the compact, json-like representation.<br> 084 * Example: <code> 085 * {value: [list, of, elements], another: value} 086 * </code> 087 * 088 * Block: expanded, traditional YAML<br> 089 * Example: <code> 090 * value: 091 * - list 092 * - of 093 * - elements 094 * another: value 095 * </code> 096 * 097 * @param style The flow style to use 098 * @return This builder (for chaining) 099 */ 100 @NonNull 101 public Builder setFlowStyle(@NonNull FlowStyle style) { 102 options.setDefaultFlowStyle(style); 103 return this; 104 } 105 106 /** 107 * Gets the flow style to be used by the resultant loader. 108 * 109 * @return The flow style 110 */ 111 @NonNull 112 public FlowStyle getFlowSyle() { 113 return options.getDefaultFlowStyle(); 114 } 115 116 @NonNull 117 @Override 118 public YAMLConfigurationLoader build() { 119 return new YAMLConfigurationLoader(this); 120 } 121 } 122 123 private final ThreadLocal<Yaml> yaml; 124 125 private YAMLConfigurationLoader(Builder builder) { 126 super(builder, new CommentHandler[] {CommentHandlers.HASH}); 127 final DumperOptions opts = builder.options; 128 this.yaml = ThreadLocal.withInitial(() -> new Yaml(opts)); 129 } 130 131 @Override 132 protected void loadInternal(ConfigurationNode node, BufferedReader reader) throws IOException { 133 node.setValue(yaml.get().load(reader)); 134 } 135 136 @Override 137 protected void saveInternal(ConfigurationNode node, Writer writer) throws IOException { 138 yaml.get().dump(node.getValue(), writer); 139 } 140 141 @NonNull 142 @Override 143 public ConfigurationNode createEmptyNode(@NonNull ConfigurationOptions options) { 144 return ConfigurationNode.root(options); 145 } 146}