001package jmri.jmrix; 002 003import java.util.List; 004import javax.annotation.CheckForNull; 005import javax.annotation.Nonnull; 006import jmri.InstanceManager; 007import jmri.InstanceManagerAutoDefault; 008import jmri.beans.Bean; 009import jmri.jmrix.internal.InternalSystemConnectionMemo; 010import jmri.SystemConnectionMemo; 011 012/** 013 * Manager for SystemConnectionMemos. Manages SystemConnectionMemos and 014 * SystemConnectionMemo registration with the InstanceManager, ensuring that no 015 * two SystemConnectionMemos have the same username or system connection prefix. 016 * Also provides an object that other objects can listen to for notification of 017 * changes in SystemConnectionMemos. 018 * 019 * @author Randall Wood Copyright 2017 020 * @author Daniel Bergqvist Copyright 2022 021 */ 022public class SystemConnectionMemoManager extends Bean implements InstanceManagerAutoDefault { 023 024 /** 025 * Property name change fired when a connection is registered. The fired 026 * event has a null old value and the added connection as the new value. 027 */ 028 public final static String CONNECTION_ADDED = "ConnectionAdded"; 029 /** 030 * Property name change fired when a connection is deregistered. The fired 031 * event has the removed connection as the old value and a null new value. 032 */ 033 public final static String CONNECTION_REMOVED = "ConnectionRemoved"; 034 035 /** 036 * Register a SystemConnectionMemo in the InstanceManager. 037 * 038 * @param memo the SystemConnectionMemo to register 039 */ 040 public void register(SystemConnectionMemo memo) { 041 log.debug("registering connection {}", memo.getUserName()); 042 043 // check for special case 044 List<SystemConnectionMemo> list = InstanceManager.getList(SystemConnectionMemo.class); 045 int size = list.size(); 046 if (size > 0 && (list.get(size - 1) instanceof InternalSystemConnectionMemo)) { 047 // last is internal, so insert before that one 048 log.debug(" putting one before end"); 049 SystemConnectionMemo internal = list.get(size - 1); 050 InstanceManager.deregister(internal, SystemConnectionMemo.class); 051 InstanceManager.store(memo, SystemConnectionMemo.class); 052 InstanceManager.store(internal, SystemConnectionMemo.class); 053 } else { 054 // just add on end 055 InstanceManager.store(memo, SystemConnectionMemo.class); 056 } 057 log.trace("fire CONNECTION_ADDED for {}", memo); 058 this.firePropertyChange(CONNECTION_ADDED, null, memo); 059 } 060 061 public void deregister(SystemConnectionMemo memo) { 062 InstanceManager.deregister(memo, SystemConnectionMemo.class); 063 log.trace("fire CONNECTION_REMOVED for {}", memo); 064 firePropertyChange(CONNECTION_REMOVED, memo, null); 065 } 066 067 /** 068 * For a given System UserName AND System Prefix, get the Connection Memo. 069 * Both must match to return the memo. 070 * @param systemPrefix System Prefix to search for. 071 * @param userName system UserName to search for. 072 * @return connection memo, else null if no memo located. 073 */ 074 @CheckForNull 075 public synchronized SystemConnectionMemo getSystemConnectionMemo(@Nonnull String systemPrefix, @Nonnull String userName) { 076 for (SystemConnectionMemo memo: InstanceManager.getList(SystemConnectionMemo.class)) { 077 if (memo.getSystemPrefix().equals(systemPrefix) && memo.getUserName().equals(userName)) { 078 return memo; 079 } 080 } 081 return null; 082 } 083 084 /** 085 * For a given System UserName, get the Connection Memo. 086 * @param userName system UserName to search for. 087 * @return connection memo, else null if no memo located. 088 */ 089 @CheckForNull 090 public synchronized SystemConnectionMemo getSystemConnectionMemoForUserName(@Nonnull String userName) { 091 for (SystemConnectionMemo memo: InstanceManager.getList(SystemConnectionMemo.class)) { 092 if (memo.getUserName().equals(userName)) { 093 return memo; 094 } 095 } 096 return null; 097 } 098 099 /** 100 * For a given System Prefix, get the Connection Memo. 101 * @param systemPrefix System Prefix to search for. 102 * @return connection memo, else null if no memo located. 103 */ 104 @CheckForNull 105 public synchronized SystemConnectionMemo getSystemConnectionMemoForSystemPrefix(@Nonnull String systemPrefix) { 106 for (SystemConnectionMemo memo: InstanceManager.getList(SystemConnectionMemo.class)) { 107 if (memo.getSystemPrefix().equals(systemPrefix)) { 108 return memo; 109 } 110 } 111 return null; 112 } 113 114 /** 115 * Check if a system connection user name is available to be used. 116 * 117 * @param userName the user name to check 118 * @return true if available; false if already in use 119 */ 120 public synchronized boolean isUserNameAvailable(@Nonnull String userName) { 121 return InstanceManager.getList(SystemConnectionMemo.class).stream().noneMatch((memo) -> (userName.equals(memo.getUserName()))); 122 } 123 124 /** 125 * Check if a system connection prefix for the system names of other objects 126 * is available to be used. 127 * 128 * @param systemPrefix the system prefix to check 129 * @return true if available; false if already in use 130 */ 131 public synchronized boolean isSystemPrefixAvailable(@Nonnull String systemPrefix) { 132 return InstanceManager.getList(SystemConnectionMemo.class).stream().noneMatch((memo) -> (memo.getSystemPrefix().equals(systemPrefix))); 133 } 134 135 /** 136 * Get the default instance of this manager. 137 * 138 * @return the default instance, created if needed 139 */ 140 public static SystemConnectionMemoManager getDefault() { 141 return InstanceManager.getDefault(SystemConnectionMemoManager.class); 142 } 143 144 /** 145 * Find the connection by its name. 146 * <p> 147 * Example:<br> 148 * LocoNetSystemConnectionMemo memo = getConnection("L2", LocoNetSystemConnectionMemo.class); 149 * </p> 150 * @param <T> The type of connection 151 * @param systemConnectionName The connection name 152 * @param clazz The class of the connection type 153 * @return The memo if found, null otherwise 154 */ 155 @CheckForNull 156 public static <T extends SystemConnectionMemo> T getConnection( 157 @Nonnull String systemConnectionName, 158 @Nonnull Class<T> clazz) { 159 160 List<T> systemConnections = jmri.InstanceManager.getList(clazz); 161 162 for (T memo : systemConnections) { 163 if (memo.getSystemPrefix().equals(systemConnectionName)) { 164 return memo; 165 } 166 } 167 168 // Connection is not found 169 return null; 170 } 171 172 /** 173 * Find the connection by its user name. 174 * <p> 175 * Example:<br> 176 * LocoNetSystemConnectionMemo memo = getConnectionByUserName("LocoNet", LocoNetSystemConnectionMemo.class); 177 * </p> 178 * @param <T> The type of connection 179 * @param userName The connection user name 180 * @param clazz The class of the connection type 181 * @return The memo if found, null otherwise 182 */ 183 @CheckForNull 184 public static <T extends SystemConnectionMemo> T getConnectionByUserName( 185 @Nonnull String userName, 186 @Nonnull Class<T> clazz) { 187 188 List<T> systemConnections = jmri.InstanceManager.getList(clazz); 189 190 for (T memo : systemConnections) { 191 if (memo.getUserName().equals(userName)) { 192 return memo; 193 } 194 } 195 196 // Connection is not found 197 return null; 198 } 199 200 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SystemConnectionMemoManager.class); 201}