001package jmri.jmrit.logixng.actions; 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 action executes a module. 018 * 019 * @author Daniel Bergqvist Copyright 2020 020 */ 021public class DigitalCallModule extends AbstractDigitalAction 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 DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.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.registerAction(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 void execute() throws JmriException { 101 Module module = _selectNamedBean.evaluateNamedBean(getConditionalNG()); 102 103 if (module == null) return; 104 105 FemaleSocket femaleSocket = module.getRootSocket(); 106 107 if (! (femaleSocket instanceof FemaleDigitalActionSocket)) { 108 log.error("module.rootSocket is not a FemaleDigitalActionSocket"); 109 return; 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 try { 122 ((FemaleDigitalActionSocket)femaleSocket).execute(); 123 } catch (ReturnException e) { 124 // Do nothing 125 } 126 127 returnSymbols(newSymbolTable, _parameterData); 128 129 conditionalNG.getStack().setCount(currentStackPos); 130 131 conditionalNG.setSymbolTable(newSymbolTable.getPrevSymbolTable()); 132 } 133 134 @Override 135 public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException { 136 throw new UnsupportedOperationException("Not supported."); 137 } 138 139 @Override 140 public int getChildCount() { 141 return 0; 142 } 143 144 @Override 145 public String getShortDescription(Locale locale) { 146 return Bundle.getMessage(locale, "DigitalCallModule_Short"); 147 } 148 149 @Override 150 public String getLongDescription(Locale locale) { 151 String moduleName = _selectNamedBean.getDescription(locale); 152 153 return Bundle.getMessage(locale, "DigitalCallModule_Long", moduleName); 154 } 155 156 /** {@inheritDoc} */ 157 @Override 158 public void setup() { 159 // Do nothing 160 } 161 162 /** {@inheritDoc} */ 163 @Override 164 public void registerListenersForThisClass() { 165 _selectNamedBean.registerListeners(); 166 } 167 168 /** {@inheritDoc} */ 169 @Override 170 public void unregisterListenersForThisClass() { 171 _selectNamedBean.unregisterListeners(); 172 } 173 174 /** {@inheritDoc} */ 175 @Override 176 public void propertyChange(PropertyChangeEvent evt) { 177 getConditionalNG().execute(); 178 } 179 180 /** {@inheritDoc} */ 181 @Override 182 public void disposeMe() { 183 } 184 185 public void addParameter( 186 String name, 187 InitialValueType initialValueType, 188 String initialValueData, 189 ReturnValueType returnValueType, 190 String returnValueData) { 191 192 _parameterData.add( 193 new Module.ParameterData( 194 name, 195 initialValueType, 196 initialValueData, 197 returnValueType, 198 returnValueData)); 199 } 200 201 public List<ParameterData> getParameterData() { 202 return _parameterData; 203 } 204 205 206 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DigitalCallModule.class); 207 208}