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