001package jmri.jmrit.logixng.util.parser; 002 003import java.lang.reflect.*; 004import java.util.*; 005 006import jmri.JmriException; 007import jmri.jmrit.logixng.SymbolTable; 008 009/** 010 * A parsed expression 011 * 012 * @author Daniel Bergqvist 2021 013 */ 014public class ExpressionNodeInstanceVariable implements ExpressionNodeWithParameter { 015 016 private final String _fieldName; 017 018 public ExpressionNodeInstanceVariable(String fieldName, Map<String, Variable> variables) throws IdentifierNotExistsException { 019 _fieldName = fieldName; 020 } 021 022 @Override 023 public Object calculate(Object parameter, SymbolTable symbolTable) throws JmriException { 024 if (parameter == null) throw new NullPointerException("Parameter is null"); 025 026 try { 027 Field field = parameter.getClass().getField(_fieldName); 028 return field.get(parameter); 029 } catch (NoSuchFieldException | IllegalAccessException ex) { 030 throw new ReflectionException("Reflection exception", ex); 031 } 032 } 033 034 /** {@inheritDoc} */ 035 @Override 036 public boolean canBeAssigned() { 037 // If the identifier is a local variable, assignment is possible. And 038 // we don't know if the identifier is a valid local variable until the 039 // expression is calculated. So we assume that it is. 040 return true; 041 } 042 043 /** {@inheritDoc} */ 044 @Override 045 public void assignValue(Object parameter, SymbolTable symbolTable, Object value) throws JmriException { 046 if (parameter == null) throw new NullPointerException("Parameter is null"); 047 048 try { 049 Field field = parameter.getClass().getField(_fieldName); 050 Class<?> type = field.getType(); 051 Object newValue; 052 if (type.isAssignableFrom(value.getClass())) newValue = value; 053 else if ((type == Byte.TYPE) && (value instanceof Long)) newValue = (byte)(long)value; 054 else if ((type == Short.TYPE) && (value instanceof Long)) newValue = (short)(long)value; 055 else if ((type == Integer.TYPE) && (value instanceof Long)) newValue = (int)(long)value; 056 else if ((type == Float.TYPE) && (value instanceof Double)) newValue = (float)(double)value; 057 else throw new RuntimeException(String.format("%s cannot be assigned to %s", value.getClass().getName(), type.getName())); 058 field.set(parameter, newValue); 059 } catch (NoSuchFieldException | IllegalAccessException ex) { 060 throw new ReflectionException("Reflection exception", ex); 061 } 062 } 063 064 /** {@inheritDoc} */ 065 @Override 066 public String getDefinitionString() { 067 return "InstanceVariable:"+_fieldName; 068 } 069 070}