001package jmri.jmrit.logixng.implementation; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.Map; 006import java.util.HashMap; 007import java.util.ServiceLoader; 008 009import javax.annotation.Nonnull; 010 011import jmri.InstanceManager; 012import jmri.InvokeOnGuiThread; 013import jmri.jmrit.logixng.*; 014import jmri.util.LoggingUtil; 015import jmri.util.ThreadingUtil; 016 017/** 018 * Class providing the basic logic of the DigitalBooleanActionManager interface. 019 * 020 * @author Dave Duchamp Copyright (C) 2007 021 * @author Daniel Bergqvist Copyright (C) 2018 022 */ 023public class DefaultDigitalBooleanActionManager extends AbstractBaseManager<MaleDigitalBooleanActionSocket> 024 implements DigitalBooleanActionManager { 025 026 private final Map<Category, List<Class<? extends Base>>> actionClassList = new HashMap<>(); 027 private MaleSocket _lastRegisteredBean; 028 029 030 public DefaultDigitalBooleanActionManager() { 031 InstanceManager.getDefault(LogixNG_Manager.class).registerManager(this); 032 033 for (DigitalBooleanActionFactory actionFactory : ServiceLoader.load(DigitalBooleanActionFactory.class)) { 034 actionFactory.init(); 035 } 036 037 for (Category category : Category.values()) { 038 actionClassList.put(category, new ArrayList<>()); 039 } 040 041 for (DigitalBooleanActionFactory actionFactory : ServiceLoader.load(DigitalBooleanActionFactory.class)) { 042 actionFactory.getClasses().forEach((entry) -> { 043// System.out.format("Add action: %s, %s%n", entry.getKey().name(), entry.getValue().getName()); 044 actionClassList.get(entry.getKey()).add(entry.getValue()); 045 }); 046 } 047 048 for (MaleDigitalBooleanActionSocketFactory maleSocketFactory : ServiceLoader.load(MaleDigitalBooleanActionSocketFactory.class)) { 049 _maleSocketFactories.add(maleSocketFactory); 050 } 051 } 052 053 /** {@inheritDoc} */ 054 @Override 055 public Class<? extends MaleSocket> getMaleSocketClass() { 056 return DefaultMaleDigitalBooleanActionSocket.class; 057 } 058 059 protected MaleDigitalBooleanActionSocket createMaleActionSocket(DigitalBooleanActionBean action) { 060 MaleDigitalBooleanActionSocket socket = new DefaultMaleDigitalBooleanActionSocket(this, action); 061 action.setParent(socket); 062 return socket; 063 } 064 065 /** {@inheritDoc} */ 066 @Override 067 public MaleSocket getLastRegisteredMaleSocket() { 068 return _lastRegisteredBean; 069 } 070 071 /** {@inheritDoc} */ 072 @Override 073 public MaleDigitalBooleanActionSocket registerBean(MaleDigitalBooleanActionSocket maleSocket) { 074 MaleDigitalBooleanActionSocket bean = super.registerBean(maleSocket); 075 _lastRegisteredBean = maleSocket; 076 return bean; 077 } 078 079 /** 080 * Remember a NamedBean Object created outside the manager. 081 * This method creates a MaleDigitalBooleanActionSocket for the action. 082 * 083 * @param action the bean 084 */ 085 @Override 086 public MaleDigitalBooleanActionSocket registerAction(@Nonnull DigitalBooleanActionBean action) 087 throws IllegalArgumentException { 088 089 if (action instanceof MaleDigitalBooleanActionSocket) { 090 throw new IllegalArgumentException("registerAction() cannot register a MaleDigitalBooleanActionSocket. Use the method register() instead."); 091 } 092 093 // Check if system name is valid 094 if (this.validSystemNameFormat(action.getSystemName()) != NameValidity.VALID) { 095 log.warn("SystemName {} is not in the correct format", action.getSystemName() ); 096 throw new IllegalArgumentException(String.format("System name is invalid: %s", action.getSystemName())); 097 } 098 099 // Keep track of the last created auto system name 100 updateAutoNumber(action.getSystemName()); 101 102 // save in the maps 103 MaleDigitalBooleanActionSocket maleSocket = createMaleActionSocket(action); 104 return registerBean(maleSocket); 105 } 106 107 @Override 108 public int getXMLOrder() { 109 return LOGIXNG_DIGITAL_BOOLEAN_ACTIONS; 110 } 111 112 @Override 113 public char typeLetter() { 114 return 'Q'; 115 } 116 117 /*.* 118 * Test if parameter is a properly formatted system name. 119 * 120 * @param systemName the system name 121 * @return enum indicating current validity, which might be just as a prefix 122 *./ 123 @Override 124 public NameValidity validSystemNameFormat(String systemName) { 125 return LogixNG_Manager.validSystemNameFormat( 126 getSubSystemNamePrefix(), systemName); 127 } 128*/ 129 @Override 130 public FemaleDigitalBooleanActionSocket createFemaleSocket( 131 Base parent, FemaleSocketListener listener, String socketName) { 132 return new DefaultFemaleDigitalBooleanActionSocket(parent, listener, socketName); 133 } 134 135 @Override 136 public Map<Category, List<Class<? extends Base>>> getActionClasses() { 137 return actionClassList; 138 } 139 140 /** {@inheritDoc} */ 141 @Override 142 public String getBeanTypeHandled(boolean plural) { 143 return Bundle.getMessage(plural ? "BeanNameDigitalBooleanActions" : "BeanNameDigitalBooleanAction"); 144 } 145 146 /** {@inheritDoc} */ 147 @Override 148 public void deleteDigitalBooleanAction(MaleDigitalBooleanActionSocket x) { 149 // delete the MaleDigitalBooleanActionSocket 150 deregister(x); 151 x.dispose(); 152 } 153 154 static volatile DefaultDigitalBooleanActionManager _instance = null; 155 156 @InvokeOnGuiThread // this method is not thread safe 157 static public DefaultDigitalBooleanActionManager instance() { 158 if (!ThreadingUtil.isGUIThread()) { 159 LoggingUtil.warnOnce(log, "instance() called on wrong thread"); 160 } 161 162 if (_instance == null) { 163 _instance = new DefaultDigitalBooleanActionManager(); 164 } 165 return (_instance); 166 } 167 168 @Override 169 public Class<MaleDigitalBooleanActionSocket> getNamedBeanClass() { 170 return MaleDigitalBooleanActionSocket.class; 171 } 172 173 @Override 174 protected MaleDigitalBooleanActionSocket castBean(MaleSocket maleSocket) { 175 return (MaleDigitalBooleanActionSocket)maleSocket; 176 } 177 178 179 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultDigitalBooleanActionManager.class); 180 181}