001/* 002 * JGrapes Event Driven Framework 003 * Copyright (C) 2017-2018 Michael N. Lipp 004 * 005 * This program is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Affero General Public License as published by 007 * the Free Software Foundation; either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License along 016 * with this program; if not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jgrapes.core; 020 021import java.util.Optional; 022import java.util.function.Supplier; 023 024/** 025 * Implemented by classes that allow arbitrary objects to be associated 026 * with instances. 027 */ 028public interface Associator { 029 030 /** 031 * Establishes a "named" association to an associated object. Note that 032 * anything that represents an id can be used as value for 033 * parameter `name`, it does not necessarily have to be a string. 034 * 035 * Passing `null` as parameter `with` clears the association. 036 * 037 * @param <A> the associator's type 038 * @param by the "name" 039 * @param with the object to be associated 040 * @return the sub channel for easy chaining 041 */ 042 @SuppressWarnings({ "PMD.ShortVariable", "PMD.AvoidDuplicateLiterals" }) 043 <A extends Associator> A setAssociated(Object by, Object with); 044 045 /** 046 * Retrieves the associated object following the association 047 * with the given "name". This general version of the method 048 * supports the retrieval of values of arbitrary types 049 * associated by any "name" types. 050 * 051 * @param by the "name" 052 * @param type the type of the value to be retrieved 053 * @param <V> the type of the value to be retrieved 054 * @return the associate with the given type, if any 055 */ 056 @SuppressWarnings("PMD.ShortVariable") 057 <V> Optional<V> associated(Object by, Class<V> type); 058 059 /** 060 * Retrieves the associated object following the association 061 * with the given "name". If no association exists, the 062 * object is created and the association is established. 063 * 064 * @param by the "name" 065 * @param supplier the supplier 066 * @param <V> the type of the value to be retrieved 067 * @return the associate, if any 068 */ 069 @SuppressWarnings({ "unchecked", "PMD.ShortVariable" }) 070 default <V> V associated(Object by, Supplier<V> supplier) { 071 return (V) associated(by, Object.class).orElseGet(() -> { 072 V associated = supplier.get(); 073 setAssociated(by, associated); 074 return associated; 075 }); 076 } 077 078 /** 079 * Retrieves the associated object following the association 080 * with the given name. This convenience methods simplifies the 081 * retrieval of String values associated by a (real) name. 082 * 083 * @param by the name 084 * @return the associate, if any 085 */ 086 @SuppressWarnings("PMD.ShortVariable") 087 default Optional<String> associated(String by) { 088 return associated(by, String.class); 089 } 090 091 /** 092 * Retrieves the associated object following the association 093 * with the given class. The associated object must be an instance 094 * of the given class. 095 * 096 * @param <V> the type of the value 097 * @param by the name 098 * @return the associate, if any 099 */ 100 @SuppressWarnings("PMD.ShortVariable") 101 default <V> Optional<V> associated(Class<V> by) { 102 return associated(by, by); 103 } 104 105 /** 106 * Assumes the associated object to be of type 107 * `Supplier<Optional<V>>`. Invokes the supplier and returns the 108 * result. 109 * 110 * @param <V> the type of the value 111 * @param by the name 112 * @return the associate, if any 113 */ 114 @SuppressWarnings({ "unchecked", "PMD.ShortVariable" }) 115 default <V> Optional<V> associatedGet(Class<V> by) { 116 return associated(by, Supplier.class) 117 .flatMap(s -> ((Supplier<Optional<V>>) s).get()); 118 } 119}