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