/** * PermissionsEx * Copyright (C) zml and PermissionsEx contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ninja.leaping.permissionsex.backend.memory; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import ninja.leaping.configurate.objectmapping.Setting; import ninja.leaping.permissionsex.backend.AbstractDataStore; import ninja.leaping.permissionsex.backend.DataStore; import ninja.leaping.permissionsex.data.ContextInheritance; import ninja.leaping.permissionsex.data.ImmutableSubjectData; import ninja.leaping.permissionsex.rank.FixedRankLadder; import ninja.leaping.permissionsex.rank.RankLadder; import ninja.leaping.permissionsex.util.GuavaCollectors; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; /** * A data store backed entirely in memory */ public class MemoryDataStore extends AbstractDataStore { public static final Factory FACTORY = new Factory("memory", MemoryDataStore.class); @Setting(comment = "Whether or not this data store will store subjects being set") private boolean track = true; private final ConcurrentMap<Map.Entry<String, String>, ImmutableSubjectData> data = new ConcurrentHashMap<>(); private final ConcurrentMap<String, RankLadder> rankLadders = new ConcurrentHashMap<>(); private volatile ContextInheritance inheritance = new MemoryContextInheritance(); public MemoryDataStore() { super(FACTORY); } @Override protected void initializeInternal() { } @Override public void close() { } @Override public CompletableFuture<ImmutableSubjectData> getDataInternal(String type, String identifier) { final Map.Entry<String, String> key = Maps.immutableEntry(type, identifier); ImmutableSubjectData ret = data.get(key); if (ret == null) { ret = new MemorySubjectData(); if (track) { final ImmutableSubjectData existingData = data.putIfAbsent(key, ret); if (existingData != null) { ret = existingData; } } } return completedFuture(ret); } @Override public CompletableFuture<ImmutableSubjectData> setDataInternal(String type, String identifier, ImmutableSubjectData data) { if (track) { this.data.put(Maps.immutableEntry(type, identifier), data); } return completedFuture(data); } @Override protected CompletableFuture<RankLadder> getRankLadderInternal(String name) { RankLadder ladder = rankLadders.get(name.toLowerCase()); if (ladder == null) { ladder = new FixedRankLadder(name, ImmutableList.<Map.Entry<String, String>>of()); } return completedFuture(ladder); } @Override protected CompletableFuture<RankLadder> setRankLadderInternal(String ladder, RankLadder newLadder) { this.rankLadders.put(ladder, newLadder); return completedFuture(newLadder); } private <T> CompletableFuture<T> completedFuture(T i) { return CompletableFuture.supplyAsync(() -> i, getManager().getAsyncExecutor()); } @Override public CompletableFuture<Boolean> isRegistered(String type, String identifier) { return completedFuture(data.containsKey(Maps.immutableEntry(type, identifier))); } @Override public Set<String> getAllIdentifiers(final String type) { return data.keySet().stream() .filter(inp -> inp.getKey().equals(type)) .map(Map.Entry::getValue) .collect(GuavaCollectors.toImmutableSet()); } @Override public Set<String> getRegisteredTypes() { return ImmutableSet.copyOf(Iterables.transform(data.keySet(), Map.Entry::getKey)); } @Override public Iterable<Map.Entry<Map.Entry<String, String>, ImmutableSubjectData>> getAll() { return Iterables.unmodifiableIterable(data.entrySet()); } @Override public Iterable<String> getAllRankLadders() { return ImmutableSet.copyOf(rankLadders.keySet()); } @Override public CompletableFuture<Boolean> hasRankLadder(String ladder) { return completedFuture(rankLadders.containsKey(ladder.toLowerCase())); } @Override public CompletableFuture<ContextInheritance> getContextInheritanceInternal() { return completedFuture(this.inheritance); } @Override public CompletableFuture<ContextInheritance> setContextInheritanceInternal(ContextInheritance inheritance) { this.inheritance = inheritance; return completedFuture(this.inheritance); } @Override protected <T> T performBulkOperationSync(Function<DataStore, T> function) { return function.apply(this); } }