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.impl.config;
018
019import ca.stellardrift.permissionsex.datastore.DataStoreContext;
020import ca.stellardrift.permissionsex.impl.PermissionsEx;
021import ca.stellardrift.permissionsex.subject.SubjectRef;
022import ca.stellardrift.permissionsex.subject.SubjectType;
023import io.leangen.geantyref.TypeToken;
024import org.checkerframework.checker.nullness.qual.Nullable;
025import org.spongepowered.configurate.ConfigurationNode;
026import org.spongepowered.configurate.serialize.SerializationException;
027import org.spongepowered.configurate.serialize.TypeSerializer;
028
029import java.lang.reflect.Type;
030import java.util.Objects;
031
032/**
033 * Serializer for {@link SubjectRef} instances.
034 */
035public final class SubjectRefSerializer implements TypeSerializer<SubjectRef<?>> {
036    public static final TypeToken<SubjectRef<?>> TYPE = new TypeToken<SubjectRef<?>>() {};
037    private final DataStoreContext engine;
038    private final @Nullable SubjectType<?> defaultType;
039
040    public SubjectRefSerializer(final DataStoreContext engine, final @Nullable SubjectType<?> defaultType) {
041        this.engine = engine;
042        this.defaultType = defaultType;
043    }
044
045    @SuppressWarnings({"unchecked", "rawtypes"})
046    @Override
047    public SubjectRef<?> deserialize(final Type type, final ConfigurationNode node) throws SerializationException {
048        final @Nullable String value = node.getString();
049        if (value == null) {
050            throw new SerializationException(node, type, "Node value was not a string");
051        }
052
053        final String[] entries = value.split(":", 2);
054        if (entries.length == 1) {
055            if (this.defaultType == null) {
056                throw new SerializationException(node, type, "No default type was specified but subject '" + value + "' has no specified type!");
057            }
058            return SubjectRef.subject((SubjectType) this.defaultType, this.defaultType.parseIdentifier(entries[0]));
059        } else {
060            return this.engine.lazySubjectRef(entries[0], entries[1]);
061        }
062    }
063
064    @Override
065    public void serialize(final Type type, final @Nullable SubjectRef<?> obj, final ConfigurationNode node) throws SerializationException {
066        if (obj == null) {
067            node.set(null);
068        } else if (Objects.equals(obj.type(), this.defaultType)) {
069            node.set(obj.serializedIdentifier());
070        } else {
071            node.set(obj.type().name() + ':' + obj.serializedIdentifier());
072        }
073    }
074}