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.context; 018 019import ca.stellardrift.permissionsex.subject.CalculatedSubject; 020import org.checkerframework.checker.nullness.qual.Nullable; 021import org.pcollections.HashTreePSet; 022 023import java.util.Set; 024import java.util.function.Consumer; 025 026import static java.util.Objects.requireNonNull; 027 028/** 029 * A specific type of context, for example {@code world}, {@code server-tag}, or {@code until}. 030 * 031 * @since 2.0.0 032 */ 033public abstract class ContextDefinition<V> { 034 private final String name; 035 036 protected ContextDefinition(final String name) { 037 this.name = requireNonNull(name, "name"); 038 } 039 040 public final ContextValue<V> createValue(final V value) { 041 return new ContextValue<>(this, value); 042 } 043 044 /** 045 * Gets the name for this context definition. 046 * 047 * @return the definition name 048 * @since 2.0.0 049 */ 050 public final String name() { 051 return this.name; 052 } 053 054 /** 055 * Given a parsed value, write data out as a string. 056 * 057 * @param canonicalValue Parsed value 058 * @return serialized form of the value 059 */ 060 public abstract String serialize(V canonicalValue); 061 062 /** 063 * Given a string (which may be in user format), return a parsed object. 064 * 065 * @param userValue the value as a string, such as when provided by user input 066 * @return V a deserialized value, or {@code null if unsuccessful} 067 */ 068 public abstract @Nullable V deserialize(String userValue); 069 070 /** 071 * Given a defined context and the active value (provided by {@link #accumulateCurrentValues(CalculatedSubject, Consumer)}), 072 * return whether the active value matches the defined value. 073 */ 074 public final boolean matches(final ContextValue<V> ctx, final V activeValue) { 075 return matches(ctx.getParsedValue(this), activeValue); 076 } 077 078 public abstract boolean matches(V ownVal, V testVal); 079 080 /** 081 * Given a player, calculate active context types 082 * 083 * @param subject The subject active contexts are being calculated for 084 * @param consumer A function that will take the returned value and add it to the active context set 085 */ 086 public abstract void accumulateCurrentValues(CalculatedSubject subject, Consumer<V> consumer); 087 088 /** 089 * Given a subject, suggest a set of values that may be valid for this context. This need not be an exhaustive list, 090 * or could even be an empty list, but allows providing users possible suggestions to what sensible values for a context may be. 091 */ 092 public Set<V> suggestValues(final CalculatedSubject subject) { 093 return HashTreePSet.empty(); 094 } 095 096 @Override 097 public String toString() { 098 return "ContextDefinition{name='" + this.name + "'}"; 099 } 100 101 @Override 102 public boolean equals(final @Nullable Object other) { 103 if (this == other) return true; 104 if (!(other instanceof ContextDefinition<?>)) return false; 105 106 return this.name.equals(((ContextDefinition<?>) other).name); 107 } 108 109 @Override 110 public int hashCode() { 111 return 31 * this.name.hashCode(); 112 } 113} 114 115