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<V>().inheritable(true);
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        }
125
126        /**
127         * Set the identifier to refer to this hint.
128         *
129         * @param identifier hint identifier
130         * @return this builder
131         * @since 4.0.0
132         */
133        public abstract Builder<V> identifier(String identifier);
134
135        /**
136         * Set the type used for this node's value.
137         *
138         * <p>Raw types are forbidden.</p>
139         *
140         * @param valueType the value type
141         * @return this builder
142         * @since 4.0.0
143         */
144        public final Builder<V> valueType(final Class<V> valueType) {
145            return this.valueType(TypeToken.get(valueType));
146        }
147
148        /**
149         * Set the type used for this node's value.
150         *
151         * <p>Raw types are forbidden.</p>
152         *
153         * @param valueType the value type
154         * @return this builder
155         * @since 4.0.0
156         */
157        public abstract Builder<V> valueType(TypeToken<V> valueType);
158
159        /**
160         * Set the default value when this hint is not present in the hierarchy.
161         *
162         * <p>This defaults to {@code null}.</p>
163         *
164         * @param defaultValue value to return on gets
165         * @return this builder
166         * @since 4.0.0
167         */
168        public abstract Builder<V> defaultValue(@Nullable V defaultValue);
169
170        /**
171         * Set whether or not the hint can be inherited.
172         *
173         * <p>Defaults to {@code true}.</p>
174         *
175         * @param inheritable if inheritable
176         * @return this builder
177         * @see #inheritable()
178         * @since 4.0.0
179         */
180        public abstract Builder<V> inheritable(boolean inheritable);
181
182        /**
183         * Create a new hint from the provided options.
184         *
185         * <p>The {@code identifier} and {@code valueType} must have been set to
186         * build a complete hint.</p>
187         *
188         * @return a new representation hint
189         * @since 4.0.0
190         */
191        public abstract RepresentationHint<V> build();
192
193    }
194
195}