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.hocon.HoconConfigurationLoader;
026import org.spongepowered.configurate.objectmapping.ConfigSerializable;
027import org.spongepowered.configurate.objectmapping.meta.Comment;
028
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
036/**
037 * Example of how to use the ObjectMapper for a simple configuration that is
038 * read to and written from.
039 *
040 * <p>Error handling is not considered in this example, but for a fully fledged
041 * application it would be essential.</p>
042 */
043public final class ObjectMapperExample {
044
045    private ObjectMapperExample() {}
046
047    public static void main(final String[] args) throws ConfigurateException {
048        final Path file = Paths.get(args[0]);
049        final HoconConfigurationLoader loader = HoconConfigurationLoader.builder()
050                .defaultOptions(opts -> opts.shouldCopyDefaults(true))
051                .path(file) // or setUrl(), or setFile(), or setSource/Sink
052                .build();
053
054        final CommentedConfigurationNode node = loader.load(); // Load from file
055        final MyConfiguration config = node.get(MyConfiguration.class); // Populate object
056
057        // Do whatever actions with the configuration, then...
058        config.itemName("Steve");
059
060        node.set(MyConfiguration.class, config); // Update the backing node
061        loader.save(node); // Write to the original file
062    }
063
064    @ConfigSerializable
065    static class MyConfiguration {
066
067        // Fields must be non-final to be modified
068
069        private @Nullable String itemName;
070
071        @Comment("Here is a comment to describe the purpose of this field")
072        private Pattern filter = Pattern.compile("cars?"); // Set defaults by initializing the field
073
074        // As long as custom classes are annotated with @ConfigSerializable, they can be nested as ordinary fields.
075        private List<Section> sections = new ArrayList<>();
076
077        // This won't be written to the file because it's marked as `transient`
078        private transient @MonotonicNonNull String decoratedName;
079
080        public @Nullable String itemName() {
081            return this.itemName;
082        }
083
084        public void itemName(final String itemName) {
085            this.itemName = requireNonNull(itemName, "itemName");
086        }
087
088        public Pattern filter() {
089            return this.filter;
090        }
091
092        public List<Section> sections() {
093            return this.sections;
094        }
095
096        public String decoratedItemName() {
097            if (this.decoratedName == null) {
098                this.decoratedName = "[" + this.itemName + "]";
099            }
100            return this.decoratedName;
101        }
102
103    }
104
105    @ConfigSerializable
106    static class Section {
107
108        private String name;
109        private UUID id;
110
111        // the ObjectMapper resolves settings based on fields -- these methods are provided as a convenience
112        public String name() {
113            return this.name;
114        }
115
116        public UUID id() {
117            return this.id;
118        }
119
120    }
121
122}