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 VetoableChangeListener { 023 024 private final LogixNG_SelectNamedBean<Module> _selectNamedBean = 025 new LogixNG_SelectNamedBean<>( 026 this, Module.class, InstanceManager.getDefault(ModuleManager.class)); 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 LogixNG_Category getCategory() { 061 return LogixNG_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 disposeMe() { 163 } 164 165 public void addParameter( 166 String name, 167 InitialValueType initialValueType, 168 String initialValueData, 169 ReturnValueType returnValueType, 170 String returnValueData) { 171 172 _parameterData.add( 173 new Module.ParameterData( 174 name, 175 initialValueType, 176 initialValueData, 177 returnValueType, 178 returnValueData)); 179 } 180 181 public List<ParameterData> getParameterData() { 182 return _parameterData; 183 } 184 185 186 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DigitalCallModule.class); 187 188}