001package jmri.jmrit.logixng.implementation; 002 003import java.beans.*; 004 005import javax.annotation.Nonnull; 006import javax.annotation.OverridingMethodsMustInvokeSuper; 007 008import jmri.InstanceManager; 009import jmri.InvokeOnGuiThread; 010import jmri.jmrit.logixng.*; 011import jmri.jmrit.logixng.util.LogixNG_Thread; 012import jmri.managers.AbstractManager; 013import jmri.util.*; 014 015/** 016 * Class providing the basic logic of the ConditionalNG_Manager interface. 017 * 018 * @author Dave Duchamp Copyright (C) 2007 019 * @author Daniel Bergqvist Copyright (C) 2018 020 * @author Dave Sand Copyright (C) 2021 021 */ 022public class DefaultConditionalNGManager extends AbstractManager<ConditionalNG> 023 implements ConditionalNG_Manager { 024 025 026 public DefaultConditionalNGManager() { 027 // LogixNGPreferences class may load plugins so we must ensure 028 // it's loaded here. 029 InstanceManager.getDefault(LogixNGPreferences.class); 030 } 031 032 /** {@inheritDoc} */ 033 @Override 034 public int getXMLOrder() { 035 return LOGIXNG_CONDITIONALNGS; 036 } 037 038 /** {@inheritDoc} */ 039 @Override 040 public char typeLetter() { 041 return 'Q'; 042 } 043 044 /** {@inheritDoc} */ 045 @Override 046 public NameValidity validSystemNameFormat(String systemName) { 047 return LogixNG_Manager.validSystemNameFormat( 048 getSubSystemNamePrefix(), systemName); 049 } 050 051 /** {@inheritDoc} */ 052 @Override 053 public ConditionalNG createConditionalNG(LogixNG logixNG, String systemName, String userName) 054 throws IllegalArgumentException { 055 056 return createConditionalNG(logixNG, systemName, userName, LogixNG_Thread.DEFAULT_LOGIXNG_THREAD); 057 } 058 059 /** {@inheritDoc} */ 060 @Override 061 public ConditionalNG createConditionalNG( 062 LogixNG logixNG, String systemName, String userName, int threadID) 063 throws IllegalArgumentException { 064 065 // Check that ConditionalNG does not already exist 066 ConditionalNG x; 067 if (userName != null && !userName.isEmpty()) { 068 x = getByUserName(logixNG, userName); 069 if (x != null) { 070 log.error("username '{}' already exists, conditionalNG is '{}'", userName, x.getDisplayName()); 071 return null; 072 } 073 } 074 075 x = getBySystemName(systemName); 076 if (x != null) { 077 log.error("systemname '{}' already exists, conditionalNG is '{}'", systemName, x.getDisplayName()); 078 return null; 079 } 080 081 // Check if system name is valid 082 if (this.validSystemNameFormat(systemName) != NameValidity.VALID) { 083 throw new IllegalArgumentException("SystemName '" + systemName + "' is not in the correct format"); 084 } 085 086 // ConditionalNG does not exist, create a new ConditionalNG 087 x = new DefaultConditionalNG(systemName, userName, threadID); 088 089 // Add the conditional to the LogixNG map 090 logixNG.addConditionalNG(x); 091 092 // Keep track of the last created auto system name 093 updateAutoNumber(systemName); 094 095 return x; 096 } 097 098 /** {@inheritDoc} */ 099 @Override 100 public ConditionalNG createConditionalNG(LogixNG logixNG, String userName) throws IllegalArgumentException { 101 return createConditionalNG(logixNG, getAutoSystemName(), userName); 102 } 103 104 /** {@inheritDoc} */ 105 @Override 106 public ConditionalNG createConditionalNG(LogixNG logixNG, String userName, int threadID) throws IllegalArgumentException { 107 return createConditionalNG(logixNG, getAutoSystemName(), userName, threadID); 108 } 109 110 /** {@inheritDoc} */ 111 @Override 112 public ConditionalNG getConditionalNG(LogixNG logixNG, String name) { 113 if (logixNG != null) { 114 ConditionalNG x = getByUserName(logixNG, name); 115 if (x != null) { 116 return x; 117 } 118 } 119 return getBySystemName(name); 120 } 121 122 /** {@inheritDoc} */ 123 @Override 124 public LogixNG getParentLogixNG(String systemName) { 125 if (systemName == null || systemName.isEmpty()) { 126 return null; 127 } 128 129 for (LogixNG logixNG : InstanceManager.getDefault(LogixNG_Manager.class).getNamedBeanSet()) { 130 for (int i = 0; i < logixNG.getNumConditionalNGs(); i++) { 131 if (systemName.equals(logixNG.getConditionalNG_SystemName(i))) { 132 return logixNG; 133 } 134 } 135 } 136 return null; 137 } 138 139 /** {@inheritDoc} */ 140 @Override 141 public ConditionalNG getByUserName(LogixNG logixNG, String name) { 142 if (logixNG != null && name != null && !name.isEmpty()) { 143 for (int i = 0; i < logixNG.getNumConditionalNGs(); i++) { 144 ConditionalNG conditionalNG = logixNG.getConditionalNG(i); 145 if (conditionalNG != null) { 146 if (name.equals(conditionalNG.getUserName())) { 147 return conditionalNG; 148 } 149 } 150 } 151 } 152 return null; 153 } 154 155 /** {@inheritDoc} */ 156 @Override 157 public ConditionalNG getBySystemName(String name) { 158 LogixNG logixNG = getParentLogixNG(name); 159 if (logixNG != null) { 160 for (int i = 0; i < logixNG.getNumConditionalNGs(); i++) { 161 if (name.equals(logixNG.getConditionalNG_SystemName(i))) { 162 return logixNG.getConditionalNG(i); 163 } 164 } 165 } 166 return null; 167 } 168 169 /** {@inheritDoc} */ 170 @Override 171 public String getBeanTypeHandled(boolean plural) { 172 return Bundle.getMessage(plural ? "BeanNameConditionalNGs" : "BeanNameConditionalNG"); 173 } 174 175 /** {@inheritDoc} */ 176 @Override 177 public void deleteConditionalNG(ConditionalNG x) { 178 // delete the ConditionalNG 179 deregister(x); 180 x.dispose(); 181 } 182 183 /** {@inheritDoc} */ 184 @Override 185 public void setLoadDisabled(boolean s) { 186 throw new UnsupportedOperationException("Not supported yet."); 187 } 188 189 /** {@inheritDoc} */ 190 @Override 191 public void setRunOnGUIDelayed(boolean value) { 192 InstanceManager.getDefault(LogixNG_Manager.class).getNamedBeanSet().forEach(logixNG -> { 193 for (int i = 0; i < logixNG.getNumConditionalNGs(); i++) { 194 if (logixNG.getConditionalNG(i) != null) { 195 logixNG.getConditionalNG(i).setRunDelayed(false); 196 } 197 } 198 }); 199 } 200 201 static volatile DefaultConditionalNGManager _instance = null; 202 203 @InvokeOnGuiThread // this method is not thread safe 204 static public DefaultConditionalNGManager instance() { 205 if (!ThreadingUtil.isGUIThread()) { 206 LoggingUtil.warnOnce(log, "instance() called on wrong thread"); 207 } 208 209 if (_instance == null) { 210 _instance = new DefaultConditionalNGManager(); 211 } 212 return (_instance); 213 } 214 215 /** {@inheritDoc} */ 216 @Override 217 public Class<ConditionalNG> getNamedBeanClass() { 218 return ConditionalNG.class; 219 } 220 221 /** 222 * Inform all registered listeners of a vetoable change.If the propertyName 223 * is "CanDelete" ALL listeners with an interest in the bean will throw an 224 * exception, which is recorded returned back to the invoking method, so 225 * that it can be presented back to the user.However if a listener decides 226 * that the bean can not be deleted then it should throw an exception with 227 * a property name of "DoNotDelete", this is thrown back up to the user and 228 * the delete process should be aborted. 229 * 230 * @param p The programmatic name of the property that is to be changed. 231 * "CanDelete" will inquire with all listeners if the item can 232 * be deleted. "DoDelete" tells the listener to delete the item. 233 * @param old The old value of the property. 234 * @throws java.beans.PropertyVetoException If the recipients wishes the 235 * delete to be aborted (see above) 236 */ 237 @OverridingMethodsMustInvokeSuper 238 public void fireVetoableChange(String p, Object old) throws PropertyVetoException { 239 PropertyChangeEvent evt = new PropertyChangeEvent(this, p, old, null); 240 for (VetoableChangeListener vc : vetoableChangeSupport.getVetoableChangeListeners()) { 241 vc.vetoableChange(evt); 242 } 243 } 244 245 /** {@inheritDoc} */ 246 @Override 247// @OverridingMethodsMustInvokeSuper 248 public final void deleteBean(@Nonnull ConditionalNG conditionalNG, @Nonnull String property) throws PropertyVetoException { 249 FemaleSocket child = conditionalNG.getFemaleSocket(); 250 if (child.isConnected()) { 251 MaleSocket maleSocket = child.getConnectedSocket(); 252 maleSocket.getManager().deleteBean(maleSocket, property); 253 } 254 255 // throws PropertyVetoException if vetoed 256 fireVetoableChange(property, conditionalNG); 257 if (property.equals("DoDelete")) { // NOI18N 258 if (conditionalNG.getLogixNG() != null) { 259 conditionalNG.getLogixNG().deleteConditionalNG(conditionalNG); 260 } 261 conditionalNG.dispose(); 262 } 263 } 264 265 266 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultConditionalNGManager.class); 267}