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 org.spongepowered.configurate.examples; 018 019import static java.util.Objects.requireNonNull; 020 021import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 022import org.checkerframework.checker.nullness.qual.Nullable; 023import org.spongepowered.configurate.CommentedConfigurationNode; 024import org.spongepowered.configurate.ConfigurateException; 025import org.spongepowered.configurate.ConfigurationNode; 026import org.spongepowered.configurate.ScopedConfigurationNode; 027import org.spongepowered.configurate.hocon.HoconConfigurationLoader; 028import org.spongepowered.configurate.objectmapping.ConfigSerializable; 029import org.spongepowered.configurate.objectmapping.ObjectMapper; 030import org.spongepowered.configurate.objectmapping.meta.Comment; 031import org.spongepowered.configurate.serialize.SerializationException; 032 033import java.nio.file.Path; 034import java.nio.file.Paths; 035import java.util.ArrayList; 036import java.util.List; 037import java.util.UUID; 038import java.util.regex.Pattern; 039 040/** 041 * Example of how to use the ObjectMapper for a simple read-only configuration. 042 * 043 * <p>Error handling is not considered in this example, but for a fully fledged 044 * application it would be essential.</p> 045 */ 046public final class ObjectMapperExample { 047 048 private ObjectMapperExample() {} 049 050 public static void main(final String[] args) throws ConfigurateException { 051 final Path file = Paths.get(args[0]); 052 final HoconConfigurationLoader loader = HoconConfigurationLoader.builder() 053 .defaultOptions(opts -> opts.shouldCopyDefaults(true)) 054 .path(file) // or setUrl(), or setFile(), or setSource/Sink 055 .build(); 056 057 final CommentedConfigurationNode node = loader.load(); // Load from file 058 final MyConfiguration config = MyConfiguration.loadFrom(node); // Populate object 059 060 // Do whatever actions with the configuration, then... 061 config.itemName("Steve"); 062 063 config.saveTo(node); // Update the backing node 064 loader.save(node); // Write to the original file 065 } 066 067 @ConfigSerializable 068 static class MyConfiguration { 069 070 private static final ObjectMapper<MyConfiguration> MAPPER; 071 072 static { 073 try { 074 MAPPER = ObjectMapper.factory().get(MyConfiguration.class); // We hold on to the instance of our ObjectMapper 075 } catch (final SerializationException e) { 076 throw new ExceptionInInitializerError(e); 077 } 078 } 079 080 public static MyConfiguration loadFrom(final ConfigurationNode node) throws SerializationException { 081 return MAPPER.load(node); 082 } 083 084 private @Nullable String itemName; 085 086 @Comment("Here is a comment to describe the purpose of this field") 087 private Pattern filter = Pattern.compile("cars?"); // Set defaults by initializing the field 088 089 // As long as custom classes are annotated with @ConfigSerializable, they can be nested as ordinary fields. 090 private List<Section> sections = new ArrayList<>(); 091 092 // This won't be written to the file because it's marked as `transient` 093 private transient @MonotonicNonNull String decoratedName; 094 095 public @Nullable String itemName() { 096 return this.itemName; 097 } 098 099 public void itemName(final String itemName) { 100 this.itemName = requireNonNull(itemName, "itemName"); 101 } 102 103 public Pattern filter() { 104 return this.filter; 105 } 106 107 public List<Section> sections() { 108 return this.sections; 109 } 110 111 public String decoratedItemName() { 112 if (this.decoratedName == null) { 113 this.decoratedName = "[" + this.itemName + "]"; 114 } 115 return this.decoratedName; 116 } 117 118 public <N extends ScopedConfigurationNode<N>> void saveTo(final N node) throws SerializationException { 119 MAPPER.save(this, node); 120 } 121 122 } 123 124 @ConfigSerializable 125 static class Section { 126 127 private String name; 128 private UUID id; 129 130 // the ObjectMapper resolves settings based on fields -- these methods are provided as a convenience 131 public String name() { 132 return this.name; 133 } 134 135 public UUID id() { 136 return this.id; 137 } 138 139 } 140 141}