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.examples;
018
019import ninja.leaping.configurate.ConfigurationNode;
020import ninja.leaping.configurate.commented.CommentedConfigurationNode;
021import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
022import ninja.leaping.configurate.objectmapping.ObjectMapper;
023import ninja.leaping.configurate.objectmapping.ObjectMappingException;
024import ninja.leaping.configurate.objectmapping.Setting;
025import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
026import org.checkerframework.checker.nullness.qual.Nullable;
027
028import java.io.IOException;
029import java.nio.file.Path;
030import java.nio.file.Paths;
031import java.util.ArrayList;
032import java.util.List;
033import java.util.UUID;
034import java.util.regex.Pattern;
035
036import static java.util.Objects.requireNonNull;
037
038/**
039 * An example of how to use the ObjectMapper for a simple read-only configuration.
040 *
041 * Error handling is not considered in this example, but for a fully fledged application it will be essential.
042 */
043public class ObjectMapperExample {
044    public static void main(String[] args) throws IOException, ObjectMappingException {
045        final Path file = Paths.get(args[0]);
046        final HoconConfigurationLoader loader = HoconConfigurationLoader.builder()
047                .setPath(file) // or setUrl(), or setFile(), or setSource/Sink
048                .build();
049
050        final CommentedConfigurationNode node = loader.load(); // Load from file
051        final MyConfiguration config = MyConfiguration.loadFrom(node); // Populate object
052
053        // Do whatever actions with the configuration, then...
054        config.setItemName("Steve");
055
056        config.saveTo(node); // Update the backing node
057        loader.save(node); // Write to the original file
058    }
059}
060
061@ConfigSerializable
062class MyConfiguration {
063    private static final ObjectMapper<MyConfiguration> MAPPER;
064
065    static {
066        try {
067            MAPPER = ObjectMapper.forClass(MyConfiguration.class); // We hold on to the instance of our ObjectMapper
068        } catch (ObjectMappingException e) {
069            throw new ExceptionInInitializerError(e);
070        }
071    }
072
073    public static MyConfiguration loadFrom(ConfigurationNode node) throws ObjectMappingException {
074        return MAPPER.bindToNew().populate(node);
075    }
076
077    @Setting(value = "item-name") // The key for a setting is normally provided by the field name, but can be overridden
078    private @Nullable String itemName;
079    @Setting(comment = "Here is a comment to describe the purpose of this field")
080    private Pattern filter = Pattern.compile("cars?"); // Set defaults by initializing the field
081
082    // As long as custom classes are annotated with @ConfigSerializable, they can be nested as ordinary fields.
083    private List<Section> sections = new ArrayList<>();
084
085    public @Nullable String getItemName() {
086        return this.itemName;
087    }
088
089    public void setItemName(String itemName) {
090        this.itemName = requireNonNull(itemName, "itemName");
091    }
092
093    public Pattern getFilter() {
094        return this.filter;
095    }
096
097    public List<Section> getSections() {
098        return this.sections;
099    }
100
101    public void saveTo(ConfigurationNode node) throws ObjectMappingException {
102        MAPPER.bind(this).serialize(node);
103    }
104}
105
106@ConfigSerializable
107class Section {
108    @Setting
109    private String name;
110
111    @Setting
112    private UUID id;
113
114    // the ObjectMapper resolves settings based on fields -- these methods are provided as a convenience
115    public String getName() {
116        return name;
117    }
118
119    public UUID getId() {
120        return id;
121    }
122}