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 com.google.common.reflect.TypeToken;
020import ninja.leaping.configurate.commented.CommentedConfigurationNode;
021import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
022import ninja.leaping.configurate.objectmapping.ObjectMappingException;
023import ninja.leaping.configurate.objectmapping.Setting;
024import ninja.leaping.configurate.reference.ConfigurationReference;
025import ninja.leaping.configurate.reference.ValueReference;
026import ninja.leaping.configurate.reference.WatchServiceListener;
027import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
028import ninja.leaping.configurate.transformation.NodePath;
029
030import java.io.IOException;
031import java.nio.file.Path;
032import java.nio.file.Paths;
033import java.util.List;
034import java.util.Objects;
035import java.util.UUID;
036
037public class ValueReferences {
038    private final WatchServiceListener listener;
039    private final ConfigurationReference<CommentedConfigurationNode> base;
040    private final ValueReference<String> name;
041    private final ValueReference<Integer> cookieCount;
042    private final ValueReference<List<TestObject>> complex;
043
044    @ConfigSerializable
045   static class TestObject {
046        @Setting
047        String name;
048        @Setting
049        UUID id = UUID.randomUUID();
050
051        @Override
052        public boolean equals(Object o) {
053            if (this == o) return true;
054            if (!(o instanceof TestObject)) return false;
055            TestObject that = (TestObject) o;
056            return name.equals(that.name) &&
057                    id.equals(that.id);
058        }
059
060        @Override
061        public int hashCode() {
062            return Objects.hash(name, id);
063        }
064
065        @Override
066        public String toString() {
067            return "TestObject{" +
068                    "name='" + name + '\'' +
069                    ", id=" + id +
070                    '}';
071        }
072    }
073
074   public ValueReferences(Path configFile) throws IOException, ObjectMappingException {
075       this.listener = WatchServiceListener.create();
076       this.base = listener.listenToConfiguration(file -> HoconConfigurationLoader.builder().setDefaultOptions(o -> o.withShouldCopyDefaults(true)).setPath(file).build(), configFile);
077       this.base.updates().subscribe($ -> System.out.println("Configuration auto-reloaded"));
078       this.base.errors().subscribe(err -> {
079           Throwable t = err.getValue();
080           System.out.println("Unable to " + err.getKey() + " the configuration: " + t.getMessage());
081           if (t.getCause() != null) {
082               System.out.println(t.getCause().getMessage());
083           }
084       });
085
086       name = this.base.referenceTo(String.class, "name");
087       this.name.subscribe(newName -> System.out.println("Reloaded, name is: " + newName));
088       cookieCount = this.base.referenceTo(Integer.class, new Object[] {"cookie-count"}, 5);
089       this.complex = this.base.referenceTo(new TypeToken<List<TestObject>>() {}, "complex");
090       this.base.save();
091   }
092
093   public void repl() {
094        boolean running = true;
095        if (System.console() == null) {
096            System.err.println("Not at an interactive prompt");
097            this.printData();
098            return;
099        }
100
101        while (running) {
102            String next = System.console().readLine(">");
103            if (next == null) {
104                break;
105            }
106            String[] cmd = next.split(" ");
107            if (cmd.length == 0) {
108                continue;
109            }
110
111            switch (cmd[0]) {
112                case "stop":
113                    running = false;
114                    break;
115                case "name":
116                    if (cmd.length < 2) {
117                        System.err.println("Not enough arguments, usage: name <new-name>");
118                        break;
119                    }
120                    name.setAndSave(cmd[1]);
121                    System.out.println("Name: " + this.name.get());
122                    break;
123                case "dump":
124                    printData();
125                    break;
126                case "help":
127                    System.out.println("Value reference tester\n" +
128                            "Commands:\n\n" +
129                            "stop: Exit the loop\n" +
130                            "name <name>: Update the name in the config file\n" +
131                            "dump: Dump all accessed data in the config file\n" +
132                            "help: Show this message"
133                    );
134                    break;
135                default:
136                    System.err.println("Unknown command '" + next + "'");
137                    System.err.println("help for help");
138            }
139        }
140   }
141
142   public void printData() {
143       System.out.println("Name: " + this.name.get());
144       System.out.println("Cookie count: " + this.cookieCount.get());
145       System.out.println("Complex: ");
146       if (this.complex.get().isEmpty()) {
147           System.out.println("(empty)");
148       } else {
149           for (TestObject obj : this.complex.get()) {
150              System.out.println("- " + obj);
151           }
152       }
153   }
154
155   public static void main(String[] args) {
156        if (args.length != 1) {
157            System.err.println("Usage: ./reference-example <file>");
158            return;
159        }
160        final Path path = Paths.get(args[0]);
161       try {
162           new ValueReferences(path).repl();
163       } catch (IOException | ObjectMappingException e) {
164           System.out.println("Error loading configuration: " + e.getMessage());
165           e.printStackTrace();
166       }
167   }
168
169}