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.minecraft.command;
018
019import ca.stellardrift.permissionsex.subject.SubjectRef;
020import cloud.commandframework.keys.CloudKey;
021import cloud.commandframework.keys.SimpleCloudKey;
022import cloud.commandframework.permission.CommandPermission;
023import cloud.commandframework.permission.PredicatePermission;
024import net.kyori.adventure.text.Component;
025import org.checkerframework.checker.nullness.qual.NonNull;
026import org.checkerframework.checker.nullness.qual.Nullable;
027import org.immutables.value.Value;
028
029import java.util.Collection;
030import java.util.Collections;
031
032import static java.util.Objects.requireNonNull;
033
034/**
035 * A representation of a permission.
036 *
037 * [value] is a dotted string
038 * [description] describes the permission's purpose, including ways it may be specialized in use
039 * [default] is the value to resolve this permission to when unset
040 */
041@Value.Immutable(builder = false)
042public abstract class Permission implements PredicatePermission<Commander> {
043
044    public static Permission of(final String permission) {
045        return of(permission, Component.empty(), 0);
046    }
047
048    public static Permission of(final String permission, final Component description) {
049        return of(permission, description, 0);
050    }
051
052    public static Permission of(final String permission, final Component component, final int defaultValue) {
053        return new PermissionImpl(permission, component, defaultValue);
054    }
055
056    public static Permission pex(final String value) {
057        return new PermissionImpl("permissionsex." + value, Component.empty(), 0);
058    }
059
060    /**
061     * A dot-separated string of permission elements.
062     *
063     * @return the permission value
064     */
065    @Value.Parameter
066    public abstract String value();
067
068    /**
069     * Get a permission with a modified value.
070     *
071     * @param value the new permission value
072     * @return a new value
073     */
074    public abstract Permission value(String value);
075
076    /**
077     * A description of the purpose of this permission.
078     *
079     * @return the description, or empty
080     */
081    @Value.Parameter
082    public abstract @Nullable Component description();
083
084    /**
085     * A default value for when this permission is unassigned.
086     *
087     * @return the default value
088     */
089    @Value.Parameter
090    @Value.Default
091    public int defaultValue() {
092        return 0;
093    }
094
095    public final Permission then(final SubjectRef<?> other) {
096        requireNonNull(other, "other");
097        return this.value(this.value() + '.' + other.type().name() + '.' + other.serializedIdentifier());
098    }
099
100    public final Permission then(final String other) {
101        requireNonNull(other, "other");
102        return this.value(this.value() + '.' + other);
103    }
104
105    @Override
106    public final @NonNull CloudKey<Void> getKey() {
107        return SimpleCloudKey.of(this.value());
108    }
109
110    @Override
111    public final boolean hasPermission(final Commander sender) {
112        return sender.hasPermission(this);
113    }
114
115    @Override
116    public final @NonNull Collection<@NonNull CommandPermission> getPermissions() {
117        return Collections.singleton(this);
118    }
119
120    @Override
121    public final String toString() {
122        return this.value();
123    }
124}