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.objectmapping.meta;
018
019import org.spongepowered.configurate.CommentedConfigurationNodeIntermediary;
020import org.spongepowered.configurate.ConfigurationNode;
021
022import java.lang.annotation.Annotation;
023import java.lang.reflect.Type;
024import java.util.ResourceBundle;
025
026/**
027 * Performs a transformation on a value annotated with a specific type.
028 *
029 * @since 4.0.0
030 */
031@FunctionalInterface
032public interface Processor<V> {
033
034    /**
035     * Transform the output node on write.
036     *
037     * @param value source value
038     * @param destination destination node
039     * @since 4.0.0
040     */
041    void process(V value, ConfigurationNode destination);
042
043    /**
044     * Provider to, given an annotation instance and the type it's on,
045     * create a {@link Processor}.
046     *
047     * @param <A> annotation type
048     * @param <T> handled value type
049     * @since 4.0.0
050     */
051    @FunctionalInterface
052    interface Factory<A extends Annotation, T> {
053
054        /**
055         * Create a new processor given the annotation and data type.
056         *
057         * @param data annotation type on record field
058         * @param value declared field type
059         * @return new processor
060         * @since 4.0.0
061         */
062        Processor<T> make(A data, Type value);
063
064    }
065
066    /**
067     * Apply comments from {@link Comment} annotation on save.
068     *
069     * @return a new processor factory
070     * @since 4.0.0
071     */
072    static Processor.Factory<Comment, Object> comments() {
073        return (data, fieldType) -> (value, destination) -> {
074            if (destination instanceof CommentedConfigurationNodeIntermediary<?>) {
075                final CommentedConfigurationNodeIntermediary<?> commented = (CommentedConfigurationNodeIntermediary<?>) destination;
076                if (data.override()) {
077                    commented.comment(data.value());
078                } else {
079                    commented.commentIfAbsent(data.value());
080                }
081            }
082        };
083    }
084
085    /**
086     * Apply localized comments from {@link Comment} annotation on save.
087     *
088     * <p>The {@link Comment#value() comment's value} will be treated as a key
089     * into {@code source}, resolved to the system default locale. Missing keys
090     * will be written literally to node.</p>
091     *
092     * @param source source bundle for comments
093     * @return a new processor factory
094     * @since 4.0.0
095     */
096    static Processor.Factory<Comment, Object> localizedComments(final ResourceBundle source) {
097        return (data, fieldType) -> {
098            final String translated = Localization.key(source, data.value());
099            return (value, destination) -> {
100                if (destination instanceof CommentedConfigurationNodeIntermediary<?>) {
101                    final CommentedConfigurationNodeIntermediary<?> commented = (CommentedConfigurationNodeIntermediary<?>) destination;
102                    if (data.override()) {
103                        commented.comment(translated);
104                    } else {
105                        commented.commentIfAbsent(translated);
106                    }
107                }
108            };
109        };
110    }
111
112}