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.subject; 018 019import ca.stellardrift.permissionsex.context.ContextDefinitionProvider; 020import ca.stellardrift.permissionsex.context.ContextValue; 021import org.checkerframework.checker.nullness.qual.Nullable; 022 023import java.util.Map; 024import java.util.Set; 025import java.util.function.BiFunction; 026import java.util.function.Function; 027import java.util.function.UnaryOperator; 028 029/** 030 * The core subject data interface. 031 * 032 * <p>This class is an immutable holder for all of a single subject's data. No inherited data is 033 * included, and no context calculations are performed when querying objects of this class.</p> 034 * 035 * <p>The global context is represented by an empty set 036 * ({@link ContextDefinitionProvider#GLOBAL_CONTEXT}), not a null value.</p> 037 * 038 * @since 2.0.0 039 */ 040public interface ImmutableSubjectData { 041 042 /** 043 * Get all non-empty segments associated with this subject. 044 * 045 * @return all segments 046 * @since 2.0.0 047 */ 048 Map<? extends Set<ContextValue<?>>, Segment> segments(); 049 050 /** 051 * Apply a transformation to every segment contained in this subject. 052 * 053 * @param transformer action to apply 054 * @return the modified subject data 055 * @since 2.0.0 056 */ 057 ImmutableSubjectData withSegments(final BiFunction<Set<ContextValue<?>>, Segment, Segment> transformer); 058 059 /** 060 * Apply a transformation to the segment at the provided contexts. 061 * 062 * <p>If no segment is present at {@code contexts}, an empty segment will be used as the 063 * input value.</p> 064 * 065 * @param contexts the contexts to modify at 066 * @param operation the operation to perform 067 * @return an updated subject data 068 * @since 2.0.0 069 */ 070 ImmutableSubjectData withSegment(final Set<ContextValue<?>> contexts, final UnaryOperator<Segment> operation); 071 072 /** 073 * Return a map derived from all segments in this data, transformed by {@code mapper}. 074 * 075 * @param mapper the mapper 076 * @param <V> the output value type 077 * @return the map 078 * @since 2.0.0 079 */ 080 <V> Map<Set<ContextValue<?>>, V> mapSegmentValues(final Function<Segment, V> mapper); 081 082 /** 083 * Get a value derived from a single segment. 084 * 085 * @param contexts the contexts to query the segment from 086 * @param mapper the transformation 087 * @param <V> the output value type 088 * @return the transformed value, or null if no segment was present at the context 089 * @since 2.0.0 090 */ 091 <V> @Nullable V mapSegment(final Set<ContextValue<?>> contexts, final Function<Segment, V> mapper); 092 093 /** 094 * Get a segment at the specified coordinates. 095 * 096 * @param contexts the context coordinates for the segment 097 * @return the segment at the coordinates, or an empty segment if none is present 098 * @since 2.0.0 099 */ 100 Segment segment(final Set<ContextValue<?>> contexts); 101 102 /** 103 * Make an updated subject data with the segment applied at the specified context set. 104 * 105 * @param contexts contexts to set at 106 * @param segment the segment to set 107 * @return an updated subject data 108 * @since 2.0.0 109 */ 110 ImmutableSubjectData withSegment(final Set<ContextValue<?>> contexts, final Segment segment); 111 112 /** 113 * Gets the contexts with data set in this subject. 114 * 115 * @return An immutable set of all sets of contexts with data stored 116 * @since 2.0.0 117 */ 118 Set<? extends Set<ContextValue<?>>> activeContexts(); 119 120 /** 121 * Create a new subject data instance, applying all data from {@code other}. 122 * 123 * <p>This will <em>add</em> to existing data, rather than overwriting.</p> 124 * 125 * @param other source to add from 126 * @return a modified subject data 127 * @since 2.0.0 128 */ 129 default ImmutableSubjectData mergeFrom(final ImmutableSubjectData other) { 130 ImmutableSubjectData output = this; 131 for (final Map.Entry<? extends Set<ContextValue<?>>, Segment> entry : other.segments().entrySet()) { 132 output = output.withSegment(entry.getKey(), output.segment(entry.getKey()).mergeFrom(entry.getValue())); 133 } 134 return output; 135 } 136 137}