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