/**
* 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.sponge;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import ninja.leaping.permissionsex.PermissionsEx;
import ninja.leaping.permissionsex.subject.CalculatedSubject;
import ninja.leaping.permissionsex.data.SubjectCache;
import ninja.leaping.permissionsex.exception.PermissionsLoadingException;
import ninja.leaping.permissionsex.subject.SubjectType;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectCollection;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.util.Tristate;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
/**
* Subject collection
*/
class PEXSubjectCollection implements SubjectCollection {
private final String identifier;
private final PermissionsExPlugin plugin;
private final SubjectType collection;
private final PEXSubject defaults;
private final LoadingCache<String, PEXSubject> subjectCache = CacheBuilder.newBuilder().build(new CacheLoader<String, PEXSubject>() {
@Override
public PEXSubject load(String identifier) throws Exception {
return new PEXSubject(identifier, PEXSubjectCollection.this);
}
});
public PEXSubjectCollection(final String identifier, final PermissionsExPlugin plugin) throws ExecutionException, PermissionsLoadingException {
this.identifier = identifier;
this.plugin = plugin;
this.collection = plugin.getManager().getSubjects(identifier);
this.defaults = this.identifier.equals(PermissionsEx.SUBJECTS_DEFAULTS) ? get(PermissionsEx.SUBJECTS_DEFAULTS) : this.plugin.getSubjects(PermissionsEx.SUBJECTS_DEFAULTS).get(identifier);
}
@Override
public String getIdentifier() {
return identifier;
}
PermissionsExPlugin getPlugin() {
return this.plugin;
}
@Override
public PEXSubject get(String identifier) {
plugin.getTimings().onGetSubject().startTimingIfSync();
try {
return subjectCache.get(identifier);
} catch (ExecutionException e) {
throw new RuntimeException(e);
} finally {
plugin.getTimings().onGetSubject().stopTimingIfSync();
}
}
public void uncache(String identifier) {
subjectCache.invalidate(identifier);
collection.uncache(identifier);
}
@Override
public boolean hasRegistered(String identifier) {
try {
return collection.isRegistered(identifier).get();
} catch (InterruptedException | ExecutionException e) {
return false;
}
}
@Override
public Iterable<Subject> getAllSubjects() {
return Iterables.transform(collection.getAllIdentifiers(), this::get);
}
@Override
public Map<Subject, Boolean> getAllWithPermission(String permission) {
return getAllWithPermission(null, permission);
}
@Override
public Map<Subject, Boolean> getAllWithPermission(Set<Context> contexts, String permission) {
final ImmutableMap.Builder<Subject, Boolean> ret = ImmutableMap.builder();
for (PEXSubject subject : subjectCache.asMap().values()) {
Tristate permissionValue = subject.getPermissionValue(contexts == null ? subject.getActiveContexts() : contexts, permission);
if (permissionValue != Tristate.UNDEFINED) {
ret.put(subject, permissionValue.asBoolean());
}
}
return ret.build();
}
/**
* Get the subject that provides defaults for subjects of this type. This subject is placed at the root of any inheritance tree involving subjects of this type.
*
* @return The subject holding defaults
*/
@Override
public Subject getDefaults() {
return this.defaults;
}
public Optional<CommandSource> getCommandSource(String identifier) {
final Function<String, Optional<CommandSource>> provider = plugin.getCommandSourceProvider(getIdentifier());
if (provider != null) {
return provider.apply(identifier);
} else {
return Optional.empty();
}
}
Iterable<PEXSubject> getActiveSubjects() {
return subjectCache.asMap().values();
}
public CalculatedSubject getCalculatedSubject(String identifier) throws PermissionsLoadingException {
try {
return plugin.getManager().getSubjects(this.identifier).get(identifier).get();
} catch (InterruptedException | ExecutionException e) {
throw new PermissionsLoadingException(e);
}
}
SubjectType getType() {
return this.collection;
}
}