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