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;
018
019import com.google.auto.value.AutoValue;
020import io.leangen.geantyref.TypeToken;
021import org.checkerframework.checker.nullness.qual.Nullable;
022
023/**
024 * A flag for configuration loaders describing how a node should be serialized.
025 *
026 * <p>A loader may not accept every representation hint available, but any
027 * understood hints should be exposed as constant fields on the loader class.
028 * Any unknown hints will be ignored.
029 *
030 * @param <V> the value type
031 * @since 4.0.0
032 */
033@AutoValue
034public abstract class RepresentationHint<V> {
035
036    /**
037     * Create a new basic representation hint.
038     *
039     * <p>The created hint will be inheritable and have no default
040     * value set.</p>
041     *
042     * @param identifier hint identifier
043     * @param valueType type of value the hint will hold
044     * @param <V> value type
045     * @return a new hint
046     * @since 4.0.0
047     */
048    public static <V> RepresentationHint<V> of(final String identifier, final Class<V> valueType) {
049        return RepresentationHint.<V>builder().identifier(identifier).valueType(valueType).build();
050    }
051
052    /**
053     * Create a new basic representation hint.
054     *
055     * <p>The created hint will be inheritable and have no default
056     * value set.</p>
057     *
058     * @param identifier hint identifier
059     * @param valueType type of value the hint will hold
060     * @param <V> value type
061     * @return a new hint
062     * @since 4.0.0
063     */
064    public static <V> RepresentationHint<V> of(final String identifier, final TypeToken<V> valueType) {
065        return RepresentationHint.<V>builder().identifier(identifier).valueType(valueType).build();
066    }
067
068    /**
069     * Create a builder for a new hint.
070     *
071     * @param <V> value type
072     * @return a new builder
073     * @since 4.0.0
074     */
075    public static <V> Builder<V> builder() {
076        return new AutoValue_RepresentationHint.Builder<>();
077    }
078
079    RepresentationHint() { }
080
081    /**
082     * An identifier used to represent this hint in error messages.
083     *
084     * @return the identifier
085     * @since 4.0.0
086     */
087    public abstract String identifier();
088
089    /**
090     * The type that values of this type have to have.
091     *
092     * @return value type
093     * @since 4.0.0
094     */
095    public abstract TypeToken<V> valueType();
096
097    /**
098     * If a value for a representation hint cannot be found by quering a node
099     * or any of this parents, the default value will be returned.
100     *
101     * @return default type
102     * @since 4.0.0
103     */
104    public abstract @Nullable V defaultValue();
105
106    /**
107     * Get whether or not this hint can draw its value from parent nodes.
108     *
109     * @return if inheritable
110     * @since 4.0.0
111     */
112    public abstract boolean inheritable();
113
114    /**
115     * A builder for {@link RepresentationHint}s.
116     *
117     * @param <V> value type
118     * @since 4.0.0
119     */
120    @AutoValue.Builder
121    public abstract static class Builder<V> {
122
123        Builder() {
124            this.inheritable(true);
125        }
126
127        /**
128         * Set the identifier to refer to this hint.
129         *
130         * @param identifier hint identifier
131         * @return this builder
132         * @since 4.0.0
133         */
134        public abstract Builder<V> identifier(String identifier);
135
136        /**
137         * Set the type used for this node's value.
138         *
139         * <p>Raw types are forbidden.</p>
140         *
141         * @param valueType the value type
142         * @return this builder
143         * @since 4.0.0
144         */
145        public final Builder<V> valueType(final Class<V> valueType) {
146            return valueType(TypeToken.get(valueType));
147        }
148
149        /**
150         * Set the type used for this node's value.
151         *
152         * <p>Raw types are forbidden.</p>
153         *
154         * @param valueType the value type
155         * @return this builder
156         * @since 4.0.0
157         */
158        public abstract Builder<V> valueType(TypeToken<V> valueType);
159
160        /**
161         * Set the default value when this hint is not present in the hierarchy.
162         *
163         * <p>This defaults to {@code null}.</p>
164         *
165         * @param defaultValue value to return on gets
166         * @return this builder
167         * @since 4.0.0
168         */
169        public abstract Builder<V> defaultValue(@Nullable V defaultValue);
170
171        /**
172         * Set whether or not the hint can be inherited.
173         *
174         * <p>Defaults to {@code true}.</p>
175         *
176         * @param inheritable if inheritable
177         * @return this builder
178         * @see #inheritable()
179         * @since 4.0.0
180         */
181        public abstract Builder<V> inheritable(boolean inheritable);
182
183        /**
184         * Create a new hint from the provided options.
185         *
186         * <p>The {@code identifier} and {@code valueType} must have been set to
187         * build a complete hint.</p>
188         *
189         * @return a new representation hint
190         * @since 4.0.0
191         */
192        public abstract RepresentationHint<V> build();
193
194    }
195
196}