001package jmri.managers; 002 003import java.util.List; 004import java.util.ArrayList; 005import java.util.SortedSet; 006 007import javax.annotation.CheckForNull; 008import javax.annotation.Nonnull; 009 010import jmri.IdTag; 011import jmri.IdTagManager; 012import jmri.Manager; 013import jmri.Reporter; 014import jmri.InstanceManager; 015import jmri.jmrix.internal.InternalSystemConnectionMemo; 016 017/** 018 * Implementation of a IdTagManager that can serve as a proxy for multiple 019 * system-specific implementations. 020 * 021 * @author Bob Jacobsen Copyright (C) 2010, 2018 022 * @author Dave Duchamp Copyright (C) 2004 023 * @author Paul Bender Copyright (C) 2019 024 */ 025public class ProxyIdTagManager extends AbstractProvidingProxyManager<IdTag> 026 implements IdTagManager { 027 028 public ProxyIdTagManager() { 029 super(); 030 } 031 032 @Override 033 public int getXMLOrder() { 034 return jmri.Manager.IDTAGS; 035 } 036 037 @Override 038 public void init() { 039 if (!isInitialised()) { 040 getDefaultManager().init(); 041 } 042 } 043 044 /** 045 * {@inheritDoc} 046 * @return true if All IdTagManagers have initialised. 047 */ 048 @Override 049 public boolean isInitialised() { 050 return defaultManager!= null && 051 getManagerList().stream().allMatch(o->((IdTagManager)o).isInitialised()); 052 } 053 054 /** 055 * {@inheritDoc} 056 * 057 * This returns the specific IdTagManager type. 058 */ 059 @Override 060 @Nonnull 061 public IdTagManager getDefaultManager() { 062 if(defaultManager != getInternalManager()){ 063 defaultManager = getInternalManager(); 064 } 065 return (IdTagManager) defaultManager; 066 } 067 068 @Override 069 protected AbstractManager<IdTag> makeInternalManager() { 070 // since this really is an internal tracking mechanisim, 071 // build the new manager and add it here. 072 DefaultIdTagManager tagMan = new DefaultIdTagManager(InstanceManager.getDefault(InternalSystemConnectionMemo.class)); 073 InstanceManager.setIdTagManager(tagMan); 074 return tagMan; 075 } 076 077 /** 078 * Locate via user name, then system name if needed. 079 * 080 * @return Null if nothing by that name exists 081 */ 082 @CheckForNull 083 @Override 084 public IdTag getIdTag(@Nonnull String name) { 085 init(); 086 return super.getNamedBean(name); 087 } 088 089 /** {@inheritDoc} */ 090 @Override 091 @Nonnull 092 public SortedSet<IdTag> getNamedBeanSet() { 093 init(); 094 return super.getNamedBeanSet(); 095 } 096 097 @Nonnull 098 @Override 099 protected IdTag makeBean(Manager<IdTag> manager, String systemName, String userName) throws IllegalArgumentException{ 100 init(); 101 return ((IdTagManager) manager).newIdTag(systemName, userName); 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 @Override 108 @Nonnull 109 public IdTag provide(@Nonnull String name) throws IllegalArgumentException { 110 return provideIdTag(name); 111 } 112 113 /** 114 * Locate via user name, then system name if needed. If that fails, create a 115 * new IdTag: If the name is a valid system name, it will be used for the 116 * new IdTag. Otherwise, the makeSystemName method will attempt to turn it 117 * into a valid system name. 118 * 119 * @return Never null under normal circumstances 120 */ 121 @Override 122 @Nonnull 123 public IdTag provideIdTag(@Nonnull String name) throws IllegalArgumentException { 124 init(); 125 return super.provideNamedBean(name); 126 } 127 128 /** 129 * Get an instance with the specified system and user names. Note that 130 * two calls with the same arguments will get the same instance; there is 131 * only one IdTag object representing a given physical light and therefore 132 * only one with a specific system or user name. 133 * <p> 134 * This will always return a valid object reference for a valid request; a 135 * new object will be created if necessary. In that case: 136 * <ul> 137 * <li>If a null reference is given for user name, no user name will be 138 * associated with the IdTag object created; a valid system name must be 139 * provided 140 * <li>If a null reference is given for the system name, a system name will 141 * _somehow_ be inferred from the user name. How this is done is system 142 * specific. Note: a future extension of this interface will add an 143 * exception to signal that this was not possible. 144 * <li>If both names are provided, the system name defines the hardware 145 * access of the desired turnout, and the user address is associated with 146 * it. 147 * </ul> 148 * Note that it is possible to make an inconsistent request if both 149 * addresses are provided, but the given values are associated with 150 * different objects. This is a problem, and we don't have a good solution 151 * except to issue warnings. This will mostly happen if you're creating 152 * IdTags when you should be looking them up. 153 * 154 * @return requested IdTag object (never null) 155 */ 156 @Override 157 @Nonnull 158 public IdTag newIdTag(@Nonnull String systemName, String userName) throws IllegalArgumentException { 159 init(); 160 return newNamedBean(systemName, userName); 161 } 162 163 @CheckForNull 164 @Override 165 public IdTag getByTagID(@Nonnull String tagID) { 166 init(); 167 return getBySystemName(makeSystemName(tagID)); 168 } 169 170 @Override 171 @Nonnull 172 public String getBeanTypeHandled(boolean plural) { 173 return Bundle.getMessage(plural ? "BeanNameIdTags" : "BeanNameIdTag"); 174 } 175 176 /** 177 * {@inheritDoc} 178 */ 179 @Override 180 public Class<IdTag> getNamedBeanClass() { 181 return IdTag.class; 182 } 183 184 private boolean stateSaved = false; 185 186 @Override 187 public void setStateStored(boolean state) { 188 stateSaved = state; 189 for (Manager<IdTag> mgr : getManagerList()) { 190 ((IdTagManager) mgr).setStateStored(state); 191 } 192 } 193 194 @Override 195 public boolean isStateStored() { 196 stateSaved = true; 197 for (Manager<IdTag> mgr: getManagerList()) { 198 if(!((IdTagManager) mgr).isStateStored()) { 199 stateSaved = false; 200 break; 201 } 202 } 203 return stateSaved; 204 } 205 206 private boolean useFastClock = false; 207 208 @Override 209 public void setFastClockUsed(boolean fastClock) { 210 useFastClock = fastClock; 211 for (Manager<IdTag> mgr : getManagerList()) { 212 ((IdTagManager) mgr).setFastClockUsed(fastClock); 213 } 214 } 215 216 @Override 217 public boolean isFastClockUsed() { 218 useFastClock = true; 219 for (Manager<IdTag> mgr: getManagerList()) { 220 if (!((IdTagManager) mgr).isFastClockUsed()) { 221 useFastClock = false; 222 break; 223 } 224 } 225 return useFastClock; 226 } 227 228 @Override 229 @Nonnull 230 public List<IdTag> getTagsForReporter(@Nonnull Reporter reporter, long threshold) { 231 init(); 232 List<IdTag> out = new ArrayList<>(); 233 for (Manager<IdTag> mgr: getManagerList()) { 234 out.addAll(((IdTagManager)mgr).getTagsForReporter(reporter, threshold)); 235 } 236 return out; 237 } 238 239}