001/*
002 * PermissionsEx
003 * Copyright (C) zml and PermissionsEx 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 ca.stellardrift.permissionsex.datastore;
018
019import ca.stellardrift.permissionsex.PermissionsEngine;
020import net.kyori.adventure.text.Component;
021import org.checkerframework.checker.nullness.qual.Nullable;
022import org.spongepowered.configurate.ConfigurationNode;
023import ca.stellardrift.permissionsex.exception.PermissionsLoadingException;
024import org.spongepowered.configurate.serialize.SerializationException;
025
026import java.util.List;
027import java.util.Locale;
028import java.util.Map;
029
030import static java.util.Objects.requireNonNull;
031
032/**
033 * A factory to create a data store from its identifier and configuration options.
034 *
035 * <p>Data store factory implementations are discovered using the
036 * JDK {@link java.util.ServiceLoader} interface.</p>
037 *
038 * @since 2.0.0
039 */
040public interface DataStoreFactory<C> {
041
042    /**
043     * Get a factory for the type identifier.
044     *
045     * <p>The type identifier is not case-sensitive.</p>
046     *
047     * @param type requested type
048     * @return a factory, or null if none is available.
049     */
050    static @Nullable DataStoreFactory<?> forType(final String type) {
051        return DataStoreFactories.REGISTRY.get(requireNonNull(type, "type").toLowerCase(Locale.ROOT));
052    }
053
054    static Map<String, DataStoreFactory<?>> all() {
055        return DataStoreFactories.REGISTRY;
056    }
057
058    /**
059     * A user-visible name for this data store type.
060     *
061     * @return the data store type name
062     */
063    Component friendlyName();
064
065    /**
066     * The name for the data store type, usable for lookup.
067     *
068     * @return data store type name
069     * @since 2.0.0
070     */
071    String name();
072
073    /**
074     * Create a new proto data-store.
075     *
076     * <p>The returned instance will have its configuration validated, but will not attempt to load any data until it
077     * is defrosted.</p>
078     *
079     * @param identifier the identifier for this specific data store instance.
080     * @param config options used to configure the data store
081     * @return a new data store instance, not yet loaded
082     * @throws PermissionsLoadingException if any of the configuration options are invalid
083     * @since 2.0.0
084     */
085    ProtoDataStore<C> create(String identifier, ConfigurationNode config) throws PermissionsLoadingException;
086
087    /**
088     * Performs any loading necessary to resolve a full data store from its definition.
089     *
090     * @param properties the data store definition
091     * @return a full data store
092     * @throws PermissionsLoadingException if the data store has data in an invalid format
093     * @since 2.0.0
094     */
095    DataStore defrost(final DataStoreContext ctx, final ProtoDataStore<C> properties) throws PermissionsLoadingException;
096
097    /**
098     * Write the configuration defined by the proto-store to a node.
099     *
100     * @param node the destination for the configuration
101     * @param protoStore the data store
102     * @throws SerializationException if unable to write data fully
103     * @since 2.0.0
104     */
105    void serialize(final ConfigurationNode node, final ProtoDataStore<C> protoStore) throws SerializationException;
106
107    /**
108     * A data store type that is used for migration from other permissions systems.
109     *
110     * <p>These data store types can discover existing data in the environment and present
111     * conversion options to the user.</p>
112     *
113     * @since 2.0.0
114     */
115    interface Convertable<C> extends DataStoreFactory<C> {
116
117        /**
118         * Return a list of all possible conversion options for this data store.
119         *
120         * @param pex the permissions engine instance
121         * @return an unmodifiable list of possible conversion results
122         * @since 2.0.0
123         */
124        List<ConversionResult> listConversionOptions(final PermissionsEngine pex);
125    }
126}