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 by the "name" 038 * @param with the object to be associated 039 * @return the sub channel for easy chaining 040 */ 041 @SuppressWarnings({ "PMD.ShortVariable", "PMD.AvoidDuplicateLiterals" }) 042 Associator setAssociated(Object by, Object with); 043 044 /** 045 * Retrieves the associated object following the association 046 * with the given "name". This general version of the method 047 * supports the retrieval of values of arbitrary types 048 * associated by any "name" types. 049 * 050 * @param by the "name" 051 * @param type the type of the value to be retrieved 052 * @param <V> the type of the value to be retrieved 053 * @return the associate with the given type, if any 054 */ 055 @SuppressWarnings("PMD.ShortVariable") 056 <V> Optional<V> associated(Object by, Class<V> type); 057 058 /** 059 * Retrieves the associated object following the association 060 * with the given "name". If no association exists, the 061 * object is created and the association is established. 062 * 063 * @param by the "name" 064 * @param supplier the supplier 065 * @param <V> the type of the value to be retrieved 066 * @return the associate, if any 067 */ 068 @SuppressWarnings({ "unchecked", "PMD.ShortVariable" }) 069 default <V> V associated(Object by, Supplier<V> supplier) { 070 return (V) associated(by, Object.class).orElseGet(() -> { 071 V associated = supplier.get(); 072 setAssociated(by, associated); 073 return associated; 074 }); 075 } 076 077 /** 078 * Retrieves the associated object following the association 079 * with the given name. This convenience methods simplifies the 080 * retrieval of String values associated by a (real) name. 081 * 082 * @param by the name 083 * @return the associate, if any 084 */ 085 @SuppressWarnings("PMD.ShortVariable") 086 default Optional<String> associated(String by) { 087 return associated(by, String.class); 088 } 089 090 /** 091 * Retrieves the associated object following the association 092 * with the given class. The associated object must be an instance 093 * of the given class. 094 * 095 * @param <V> the type of the value 096 * @param by the name 097 * @return the associate, if any 098 */ 099 @SuppressWarnings("PMD.ShortVariable") 100 default <V> Optional<V> associated(Class<V> by) { 101 return associated(by, by); 102 } 103 104 /** 105 * Assumes the associated object to be of type 106 * `Supplier<Optional<V>>`. Invokes the supplier and returns the 107 * result. 108 * 109 * @param <V> the type of the value 110 * @param by the name 111 * @return the associate, if any 112 */ 113 @SuppressWarnings({ "unchecked", "PMD.ShortVariable" }) 114 default <V> Optional<V> associatedGet(Class<V> by) { 115 return associated(by, Supplier.class) 116 .flatMap(s -> ((Supplier<Optional<V>>) s).get()); 117 } 118}