001package jmri.jmrit.logixng.expressions; 002 003import java.beans.*; 004import java.util.*; 005 006import jmri.*; 007import jmri.jmrit.logixng.*; 008import jmri.jmrit.logixng.Module; 009import jmri.jmrit.logixng.Module.ParameterData; 010import jmri.jmrit.logixng.Module.ReturnValueType; 011import jmri.jmrit.logixng.SymbolTable.InitialValueType; 012import jmri.jmrit.logixng.implementation.DefaultSymbolTable; 013import jmri.jmrit.logixng.util.LogixNG_SelectNamedBean; 014import jmri.jmrit.logixng.util.parser.ParserException; 015 016/** 017 * This expression evaluates a module. 018 * 019 * @author Daniel Bergqvist Copyright 2021 020 */ 021public class DigitalCallModule extends AbstractDigitalExpression 022 implements PropertyChangeListener, VetoableChangeListener { 023 024 private final LogixNG_SelectNamedBean<Module> _selectNamedBean = 025 new LogixNG_SelectNamedBean<>( 026 this, Module.class, InstanceManager.getDefault(ModuleManager.class), this); 027 private final List<ParameterData> _parameterData = new ArrayList<>(); 028 029 public DigitalCallModule(String sys, String user) 030 throws BadUserNameException, BadSystemNameException { 031 super(sys, user); 032 } 033 034 @Override 035 public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws ParserException { 036 DigitalExpressionManager manager = InstanceManager.getDefault(DigitalExpressionManager.class); 037 String sysName = systemNames.get(getSystemName()); 038 String userName = userNames.get(getSystemName()); 039 if (sysName == null) sysName = manager.getAutoSystemName(); 040 DigitalCallModule copy = new DigitalCallModule(sysName, userName); 041 copy.setComment(getComment()); 042 _selectNamedBean.copy(copy._selectNamedBean); 043 for (ParameterData data : _parameterData) { 044 copy.addParameter( 045 data.getName(), 046 data.getInitialValueType(), 047 data.getInitialValueData(), 048 data.getReturnValueType(), 049 data.getReturnValueData()); 050 } 051 return manager.registerExpression(copy); 052 } 053 054 public LogixNG_SelectNamedBean<Module> getSelectNamedBean() { 055 return _selectNamedBean; 056 } 057 058 /** {@inheritDoc} */ 059 @Override 060 public Category getCategory() { 061 return Category.FLOW_CONTROL; 062 } 063 064 /** 065 * Return the symbols 066 * @param symbolTable the symbol table 067 * @param symbolDefinitions list of symbols to return 068 * @throws jmri.JmriException if an exception occurs 069 */ 070 public void returnSymbols( 071 DefaultSymbolTable symbolTable, Collection<ParameterData> symbolDefinitions) 072 throws JmriException { 073 074 for (ParameterData parameter : symbolDefinitions) { 075 Object returnValue = symbolTable.getValue(parameter.getName()); 076 077 switch (parameter.getReturnValueType()) { 078 case None: 079 break; 080 081 case LocalVariable: 082 symbolTable.getPrevSymbolTable() 083 .setValue(parameter.getReturnValueData(), returnValue); 084 break; 085 086 case Memory: 087 Memory m = InstanceManager.getDefault(MemoryManager.class).getNamedBean(parameter.getReturnValueData()); 088 if (m != null) m.setValue(returnValue); 089 break; 090 091 default: 092 log.error("definition.returnValueType has invalid value: {}", parameter.getReturnValueType().name()); 093 throw new IllegalArgumentException("definition._returnValueType has invalid value: " + parameter.getReturnValueType().name()); 094 } 095 } 096 } 097 098 /** {@inheritDoc} */ 099 @Override 100 public boolean evaluate() throws JmriException { 101 Module module = _selectNamedBean.evaluateNamedBean(getConditionalNG()); 102 103 if (module == null) return false; 104 105 FemaleSocket femaleSocket = module.getRootSocket(); 106 107 if (! (femaleSocket instanceof FemaleDigitalExpressionSocket)) { 108 log.error("module.rootSocket is not a FemaleDigitalExpressionSocket"); 109 return false; 110 } 111 112 ConditionalNG conditionalNG = getConditionalNG(); 113 114 int currentStackPos = conditionalNG.getStack().getCount(); 115 116 DefaultSymbolTable newSymbolTable = new DefaultSymbolTable(conditionalNG); 117 newSymbolTable.createSymbols(conditionalNG.getSymbolTable(), _parameterData); 118 newSymbolTable.createSymbols(module.getLocalVariables()); 119 conditionalNG.setSymbolTable(newSymbolTable); 120 121 boolean result = ((FemaleDigitalExpressionSocket)femaleSocket).evaluate(); 122 123 returnSymbols(newSymbolTable, _parameterData); 124 125 conditionalNG.getStack().setCount(currentStackPos); 126 127 conditionalNG.setSymbolTable(newSymbolTable.getPrevSymbolTable()); 128 129 return result; 130 } 131 132 @Override 133 public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException { 134 throw new UnsupportedOperationException("Not supported."); 135 } 136 137 @Override 138 public int getChildCount() { 139 return 0; 140 } 141 142 @Override 143 public String getShortDescription(Locale locale) { 144 return Bundle.getMessage(locale, "DigitalCallModule_Short"); 145 } 146 147 @Override 148 public String getLongDescription(Locale locale) { 149 String moduleName = _selectNamedBean.getDescription(locale); 150 151 return Bundle.getMessage(locale, "DigitalCallModule_Long", moduleName); 152 } 153 154 /** {@inheritDoc} */ 155 @Override 156 public void setup() { 157 // Do nothing 158 } 159 160 /** {@inheritDoc} */ 161 @Override 162 public void registerListenersForThisClass() { 163 _selectNamedBean.registerListeners(); 164 } 165 166 /** {@inheritDoc} */ 167 @Override 168 public void unregisterListenersForThisClass() { 169 _selectNamedBean.unregisterListeners(); 170 } 171 172 /** {@inheritDoc} */ 173 @Override 174 public void propertyChange(PropertyChangeEvent evt) { 175 getConditionalNG().execute(); 176 } 177 178 /** {@inheritDoc} */ 179 @Override 180 public void disposeMe() { 181 } 182 183 public void addParameter( 184 String name, 185 InitialValueType initialValueType, 186 String initialValueData, 187 ReturnValueType returnValueType, 188 String returnValueData) { 189 190 _parameterData.add( 191 new Module.ParameterData( 192 name, 193 initialValueType, 194 initialValueData, 195 returnValueType, 196 returnValueData)); 197 } 198 199 public List<ParameterData> getParameterData() { 200 return _parameterData; 201 } 202 203 204 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DigitalCallModule.class); 205 206}