001/* 002 * Trident - A Multithreaded Server Alternative 003 * Copyright 2014 The TridentSDK Team 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 net.tridentsdk.util; 018 019import jdk.nashorn.internal.ir.annotations.Immutable; 020 021import javax.annotation.concurrent.NotThreadSafe; 022import javax.annotation.concurrent.ThreadSafe; 023import java.util.function.BiConsumer; 024import java.util.function.BiFunction; 025 026/** 027 * A pair of objects 028 * 029 * <p>This class has no constructor. Rather, it has several different factory methods that instantiate 030 * internal implementations of the Pair. For most intents and purposes, one would use the {@code mutable[XXX]()} 031 * factory methods, depending on the context of usage.</p> 032 * 033 * @author The TridentSDK Team 034 */ 035public abstract class Pair<K, V> { 036 /** 037 * Creates a new mutable pair 038 * 039 * @param <K> the key type 040 * @param <V> the value type 041 * @return the new mutable pair 042 */ 043 public static <K, V> Pair<K, V> mutable() { 044 return new MutablePair<>(null, null); 045 } 046 047 /** 048 * Creates a new mutable pair with the given start arguments 049 * 050 * @param key the key initial value 051 * @param value the value initial value 052 * @param <K> the key type 053 * @param <V> the value type 054 * @return the new mutable pair 055 */ 056 public static <K, V> Pair<K, V> mutable(K key, V value) { 057 return new MutablePair<>(key, value); 058 } 059 060 /** 061 * Creates a new thread safe pair 062 * 063 * @param <K> the key type 064 * @param <V> the value type 065 * @return the new thread safe pair 066 */ 067 public static <K, V> Pair<K, V> threadSafe() { 068 return new VolatilePair<>(null, null); 069 } 070 071 /** 072 * Creates a new thread safe pair with the given start arguments 073 * 074 * @param key the key initial value 075 * @param value the value initial value 076 * @param <K> the key type 077 * @param <V> the value type 078 * @return the new thread safe pair 079 */ 080 public static <K, V> Pair<K, V> threadSafe(K key, V value) { 081 return new VolatilePair<>(key, value); 082 } 083 084 /** 085 * Creates a new immutable pair with the given arguments 086 * 087 * @param key the key value 088 * @param value the value value 089 * @param <K> the key type 090 * @param <V> the value type 091 * @return the new immutable pair 092 */ 093 public static <K, V> Pair<K, V> immutable(K key, V value) { 094 return new ImmutablePair<>(key, value); 095 } 096 097 private final boolean immutable; 098 099 Pair(boolean immutable) { 100 this.immutable = immutable; 101 } 102 103 /** 104 * Obtains the key in this pair 105 * 106 * @return the key 107 */ 108 public abstract K key(); 109 110 /** 111 * Obtains the value in this pair 112 * 113 * @return the value 114 */ 115 public abstract V val(); 116 117 /** 118 * Processes the pair 119 * 120 * @param consumer the key-value reader 121 */ 122 public void read(BiConsumer<K, V> consumer) { 123 consumer.accept(key(), val()); 124 } 125 126 /** 127 * Reads both key and value and returns a result 128 * 129 * @param func the reader 130 * @param <T> the type to be returned 131 * @return the function's result 132 */ 133 public <T> T read(BiFunction<K, V, T> func) { 134 return func.apply(key(), val()); 135 } 136 137 /** 138 * Copies the key and value of the current pair to another pair 139 * 140 * @param pair the pair to transfer to 141 * @throws UnsupportedOperationException if the given pair is immutable 142 */ 143 public void transfer(Pair<K, V> pair) { 144 pair.set(key(), val()); 145 } 146 147 /** 148 * Sets the key of this pair 149 * 150 * @param key the key to set 151 * @throws UnsupportedOperationException if the pair is immutable 152 */ 153 public abstract void setKey(K key); 154 155 /** 156 * Sets the value of this pair 157 * 158 * @param val the value to set 159 * @throws UnsupportedOperationException if the pair is immutable 160 */ 161 public abstract void setVal(V val); 162 163 /** 164 * Sets both the key and values of this pair 165 * 166 * @param key the key to set 167 * @param val the value to set 168 * @throws UnsupportedOperationException if the pair is immutable 169 */ 170 public void set(K key, V val) { 171 setKey(key); 172 setVal(val); 173 } 174 175 /** 176 * Checks this pair in order to ensure whether it is immutable or not 177 * 178 * @return {@code true} if the pair is immutable, {@code false} if not 179 */ 180 public boolean isImmutable() { 181 return this.immutable; 182 } 183 184 @ThreadSafe 185 private static class VolatilePair<K, V> extends Pair<K, V> { 186 private volatile K key; 187 private volatile V value; 188 189 public VolatilePair(K key, V value) { 190 super(false); 191 this.key = key; 192 this.value = value; 193 } 194 195 @Override 196 public K key() { 197 return key; 198 } 199 200 @Override 201 public V val() { 202 return value; 203 } 204 205 @Override 206 public void setKey(K key) { 207 this.key = key; 208 } 209 210 @Override 211 public void setVal(V val) { 212 this.value = val; 213 } 214 } 215 216 @NotThreadSafe 217 private static class MutablePair<K, V> extends Pair<K, V> { 218 private K key; 219 private V value; 220 221 public MutablePair(K key, V value) { 222 super(false); 223 this.key = key; 224 this.value = value; 225 } 226 227 @Override 228 public K key() { 229 return key; 230 } 231 232 @Override 233 public V val() { 234 return value; 235 } 236 237 @Override 238 public void setKey(K key) { 239 this.key = key; 240 } 241 242 @Override 243 public void setVal(V val) { 244 this.value = val; 245 } 246 } 247 248 @Immutable 249 private static class ImmutablePair<K, V> extends Pair<K, V> { 250 private final K key; 251 private final V value; 252 253 public ImmutablePair(K key, V value) { 254 super(true); 255 this.key = key; 256 this.value = value; 257 } 258 259 @Override 260 public K key() { 261 return key; 262 } 263 264 @Override 265 public V val() { 266 return value; 267 } 268 269 @Override 270 public void setKey(K key) { 271 throw new UnsupportedOperationException("Immutable pair"); 272 } 273 274 @Override 275 public void setVal(V val) { 276 throw new UnsupportedOperationException("Immutable pair"); 277 } 278 } 279}