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.backend.memory;
018
019import com.google.common.collect.ImmutableList;
020import com.google.common.collect.ImmutableMap;
021import com.google.common.collect.Lists;
022import org.spongepowered.configurate.objectmapping.ConfigSerializable;
023import ca.stellardrift.permissionsex.context.ContextValue;
024import ca.stellardrift.permissionsex.context.ContextInheritance;
025import org.spongepowered.configurate.objectmapping.meta.Setting;
026
027import java.util.Collections;
028import java.util.HashMap;
029import java.util.List;
030import java.util.Map;
031
032/**
033 * Context inheritance data structure
034 */
035@ConfigSerializable
036public class MemoryContextInheritance implements ContextInheritance {
037    @Setting("context-inheritance")
038    private Map<String, List<String>> contextInheritance = new HashMap<>();
039
040    protected MemoryContextInheritance() {
041
042    }
043
044    protected MemoryContextInheritance(Map<String, List<String>> data) {
045        this.contextInheritance = data;
046    }
047
048    @Override
049    public List<ContextValue<?>> parents(ContextValue<?> context) {
050        final List<String> inheritance = contextInheritance.get(ctxToString(context));
051        if (inheritance == null) {
052            return Collections.emptyList();
053        }
054
055        return Collections.unmodifiableList(Lists.transform(inheritance, MemoryContextInheritance::ctxFromString));
056    }
057
058    @Override
059    public ContextInheritance parents(ContextValue<?> context, List<ContextValue<?>> parents) {
060        final Map<String, List<String>> newData = new HashMap<>(contextInheritance);
061        newData.put(ctxToString(context), ImmutableList.copyOf(Lists.transform(ImmutableList.copyOf(parents), MemoryContextInheritance::ctxToString)));
062        return newCopy(newData);
063    }
064
065    @Override
066    public Map<ContextValue<?>, List<ContextValue<?>>> allParents() {
067        ImmutableMap.Builder<ContextValue<?>, List<ContextValue<?>>> ret = ImmutableMap.builder();
068        for (Map.Entry<String, List<String>> entry : contextInheritance.entrySet()) {
069            ret.put(ctxFromString(entry.getKey()), Lists.transform(entry.getValue(), MemoryContextInheritance::ctxFromString));
070        }
071        return ret.build();
072    }
073
074    protected MemoryContextInheritance newCopy(Map<String, List<String>> raw) {
075        return new MemoryContextInheritance(raw);
076    }
077
078    public static MemoryContextInheritance fromExistingContextInheritance(ContextInheritance inheritance) {
079        if (inheritance instanceof MemoryContextInheritance) {
080            return ((MemoryContextInheritance) inheritance);
081        } else {
082            Map<String, List<String>> data = new HashMap<>();
083            for (Map.Entry<ContextValue<?>, List<ContextValue<?>>> ent : inheritance.allParents().entrySet()) {
084                data.put(ctxToString(ent.getKey()), Lists.transform(ent.getValue(), MemoryContextInheritance::ctxToString));
085            }
086            return new MemoryContextInheritance(data);
087        }
088    }
089
090    public static ContextValue<?> ctxFromString(String input) {
091        final String[] values = input.split(":", 2);
092        if (values.length != 2) {
093            throw new IllegalArgumentException("Invalid format for context!");
094        }
095        return new ContextValue<>(values[0], values[1]);
096    }
097
098    public static String ctxToString(ContextValue<?> input) {
099        return input.key() + ":" + input.rawValue();
100    }
101
102
103}