001package jmri.jmrit.logixng.implementation; 002 003import java.beans.*; 004import java.io.PrintWriter; 005import java.util.*; 006 007import javax.annotation.Nonnull; 008import javax.annotation.OverridingMethodsMustInvokeSuper; 009 010import jmri.*; 011import jmri.jmrit.logixng.*; 012import jmri.managers.AbstractManager; 013import jmri.util.LoggingUtil; 014import jmri.util.ThreadingUtil; 015 016/** 017 * Class providing the basic logic of the GlobalVariable_Manager interface. 018 * 019 * @author Dave Duchamp Copyright (C) 2007 020 * @author Daniel Bergqvist Copyright (C) 2022 021 */ 022public class DefaultGlobalVariableManager extends AbstractManager<GlobalVariable> 023 implements GlobalVariableManager { 024 025 026 public DefaultGlobalVariableManager() { 027 // The GlobalVariablePreferences class may load plugins so we must ensure 028 // it's loaded here. 029 InstanceManager.getDefault(LogixNGPreferences.class); 030 } 031 032 @Override 033 public int getXMLOrder() { 034 return LOGIXNG_GLOBAL_VARIABLES; 035 } 036 037 @Override 038 public char typeLetter() { 039 return 'Q'; 040 } 041 042 /** 043 * Test if parameter is a properly formatted system name. 044 * 045 * @param systemName the system name 046 * @return enum indicating current validity, which might be just as a prefix 047 */ 048 @Override 049 public NameValidity validSystemNameFormat(String systemName) { 050 return LogixNG_Manager.validSystemNameFormat( 051 getSubSystemNamePrefix(), systemName); 052 } 053 054 /** 055 * Method to create a new GlobalVariable if the GlobalVariable does not exist. 056 * <p> 057 * Returns null if a GlobalVariable with the same systemName or userName 058 * already exists, or if there is trouble creating a new GlobalVariable. 059 */ 060 @Override 061 public GlobalVariable createGlobalVariable(String systemName, String userName) 062 throws IllegalArgumentException { 063 064 // Check that GlobalVariable does not already exist 065 GlobalVariable x; 066 if (userName != null && !userName.equals("")) { 067 x = getByUserName(userName); 068 if (x != null) { 069 return null; 070 } 071 } 072 x = getBySystemName(systemName); 073 if (x != null) { 074 return null; 075 } 076 // Check if system name is valid 077 if (this.validSystemNameFormat(systemName) != NameValidity.VALID) { 078 throw new IllegalArgumentException("SystemName " + systemName + " is not in the correct format"); 079 } 080 // GlobalVariable does not exist, create a new GlobalVariable 081 x = new DefaultGlobalVariable(systemName, userName); 082 // save in the maps 083 register(x); 084 085 // Keep track of the last created auto system name 086 updateAutoNumber(systemName); 087 088 return x; 089 } 090 091 @Override 092 public GlobalVariable createGlobalVariable(String userName) throws IllegalArgumentException { 093 return createGlobalVariable(getAutoSystemName(), userName); 094 } 095 096 @Override 097 public GlobalVariable getGlobalVariable(String name) { 098 GlobalVariable x = getByUserName(name); 099 if (x != null) { 100 return x; 101 } 102 return getBySystemName(name); 103 } 104 105 @Override 106 public GlobalVariable getByUserName(String name) { 107 return _tuser.get(name); 108 } 109 110 @Override 111 public GlobalVariable getBySystemName(String name) { 112 return _tsys.get(name); 113 } 114 115 /** {@inheritDoc} */ 116 @Override 117 public String getBeanTypeHandled(boolean plural) { 118 return Bundle.getMessage(plural ? "BeanNameGlobalVariables" : "BeanNameGlobalVariable"); 119 } 120 121 /** {@inheritDoc} */ 122 @Override 123 public void deleteGlobalVariable(GlobalVariable x) { 124 // delete the GlobalVariable 125 deregister(x); 126 x.dispose(); 127 } 128 129 /** {@inheritDoc} */ 130 @Override 131 public void printTree(Locale locale, PrintWriter writer, String indent) { 132 for (GlobalVariable globalVariable : getNamedBeanSet()) { 133 writer.append(String.format( 134 "Global variable: System name: %s, User name: %s, Initial value type: %s, Initial value data: %s", 135 globalVariable.getSystemName(), globalVariable.getUserName(), 136 globalVariable.getInitialValueType().toString(), globalVariable.getInitialValueData())); 137 writer.println(); 138 } 139 writer.println(); 140 } 141 142 static volatile DefaultGlobalVariableManager _instance = null; 143 144 @InvokeOnGuiThread // this method is not thread safe 145 static public DefaultGlobalVariableManager instance() { 146 if (!ThreadingUtil.isGUIThread()) { 147 LoggingUtil.warnOnce(log, "instance() called on wrong thread"); 148 } 149 150 if (_instance == null) { 151 _instance = new DefaultGlobalVariableManager(); 152 } 153 return (_instance); 154 } 155 156 /** {@inheritDoc} */ 157 @Override 158 public Class<GlobalVariable> getNamedBeanClass() { 159 return GlobalVariable.class; 160 } 161 162 /** 163 * Inform all registered listeners of a vetoable change.If the propertyName 164 * is "CanDelete" ALL listeners with an interest in the bean will throw an 165 * exception, which is recorded returned back to the invoking method, so 166 * that it can be presented back to the user.However if a listener decides 167 * that the bean can not be deleted then it should throw an exception with 168 * a property name of "DoNotDelete", this is thrown back up to the user and 169 * the delete process should be aborted. 170 * 171 * @param p The programmatic name of the property that is to be changed. 172 * "CanDelete" will inquire with all listeners if the item can 173 * be deleted. "DoDelete" tells the listener to delete the item. 174 * @param old The old value of the property. 175 * @throws java.beans.PropertyVetoException If the recipients wishes the 176 * delete to be aborted (see above) 177 */ 178 @OverridingMethodsMustInvokeSuper 179 public void fireVetoableChange(String p, Object old) throws PropertyVetoException { 180 PropertyChangeEvent evt = new PropertyChangeEvent(this, p, old, null); 181 for (VetoableChangeListener vc : vetoableChangeSupport.getVetoableChangeListeners()) { 182 vc.vetoableChange(evt); 183 } 184 } 185 186 /** {@inheritDoc} */ 187 @Override 188// @OverridingMethodsMustInvokeSuper 189 public final void deleteBean(@Nonnull GlobalVariable globalVariable, @Nonnull String property) throws PropertyVetoException { 190 // throws PropertyVetoException if vetoed 191 fireVetoableChange(property, globalVariable); 192 if (property.equals("DoDelete")) { // NOI18N 193 deregister(globalVariable); 194 globalVariable.dispose(); 195 } 196 } 197 198 199 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultGlobalVariableManager.class); 200 201}