001package jmri.jmrit.logixng.expressions; 002 003import java.util.Locale; 004import java.util.Map; 005 006import jmri.InstanceManager; 007import jmri.JmriException; 008import jmri.jmrit.logixng.Base; 009import jmri.jmrit.logixng.Category; 010import jmri.jmrit.logixng.FemaleSocket; 011import jmri.jmrit.logixng.FemaleSocketListener; 012import jmri.jmrit.logixng.SocketAlreadyConnectedException; 013import jmri.jmrit.logixng.DigitalExpressionManager; 014import jmri.jmrit.logixng.FemaleDigitalExpressionSocket; 015import jmri.jmrit.logixng.MaleSocket; 016 017/** 018 * An Expression that returns True only once while its child expression returns 019 * True. 020 * <P> 021 * The first time the child expression returns True, this expression returns 022 * True. After that, this expression returns False until the child expression 023 * returns False and again returns True. 024 * 025 * @author Daniel Bergqvist Copyright 2018 026 */ 027public class TriggerOnce extends AbstractDigitalExpression implements FemaleSocketListener { 028 029 private String _childExpressionSystemName; 030 private final FemaleDigitalExpressionSocket _childExpression; 031 private boolean _childLastState = false; 032 033 034 public TriggerOnce(String sys, String user) { 035 036 super(sys, user); 037 038 _childExpression = InstanceManager.getDefault(DigitalExpressionManager.class) 039 .createFemaleSocket(this, this, "E"); 040 } 041 042 @Override 043 public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException { 044 DigitalExpressionManager manager = InstanceManager.getDefault(DigitalExpressionManager.class); 045 String sysName = systemNames.get(getSystemName()); 046 String userName = userNames.get(getSystemName()); 047 if (sysName == null) sysName = manager.getAutoSystemName(); 048 TriggerOnce copy = new TriggerOnce(sysName, userName); 049 copy.setComment(getComment()); 050 return manager.registerExpression(copy).deepCopyChildren(this, systemNames, userNames); 051 } 052 053 /** {@inheritDoc} */ 054 @Override 055 public Category getCategory() { 056 return Category.OTHER; 057 } 058 059 /** {@inheritDoc} */ 060 @Override 061 public boolean evaluate() throws JmriException { 062 if (_childExpression.evaluate() && !_childLastState) { 063 _childLastState = true; 064 return true; 065 } 066 _childLastState = _childExpression.evaluate(); 067 return false; 068 } 069 070 @Override 071 public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException { 072 if (index == 0) { 073 return _childExpression; 074 } else { 075 throw new IllegalArgumentException( 076 String.format("index has invalid value: %d", index)); 077 } 078 } 079 080 @Override 081 public int getChildCount() { 082 return 1; 083 } 084 085 @Override 086 public void connected(FemaleSocket socket) { 087 if (socket == _childExpression) { 088 _childExpressionSystemName = socket.getConnectedSocket().getSystemName(); 089 } else { 090 throw new IllegalArgumentException("unkown socket"); 091 } 092 } 093 094 @Override 095 public void disconnected(FemaleSocket socket) { 096 if (socket == _childExpression) { 097 _childExpressionSystemName = null; 098 } else { 099 throw new IllegalArgumentException("unkown socket"); 100 } 101 } 102 103 @Override 104 public String getShortDescription(Locale locale) { 105 return Bundle.getMessage(locale, "TriggerOnce_Short"); 106 } 107 108 @Override 109 public String getLongDescription(Locale locale) { 110 return Bundle.getMessage(locale, "TriggerOnce_Long"); 111 } 112 113 public String getChildSocketSystemName() { 114 return _childExpressionSystemName; 115 } 116 117 public void setChildSocketSystemName(String systemName) { 118 _childExpressionSystemName = systemName; 119 } 120 121 /** {@inheritDoc} */ 122 @Override 123 public void setup() { 124 try { 125 if ( !_childExpression.isConnected() 126 || !_childExpression.getConnectedSocket().getSystemName() 127 .equals(_childExpressionSystemName)) { 128 129 String socketSystemName = _childExpressionSystemName; 130 _childExpression.disconnect(); 131 if (socketSystemName != null) { 132 MaleSocket maleSocket = 133 InstanceManager.getDefault(DigitalExpressionManager.class) 134 .getBySystemName(socketSystemName); 135 if (maleSocket != null) { 136 _childExpression.connect(maleSocket); 137 maleSocket.setup(); 138 } else { 139 log.error("cannot load digital expression {}", socketSystemName); 140 } 141 } 142 } else { 143 _childExpression.getConnectedSocket().setup(); 144 } 145 } catch (SocketAlreadyConnectedException ex) { 146 // This shouldn't happen and is a runtime error if it does. 147 throw new RuntimeException("socket is already connected"); 148 } 149 } 150 151 /** {@inheritDoc} */ 152 @Override 153 public void registerListenersForThisClass() { 154 } 155 156 /** {@inheritDoc} */ 157 @Override 158 public void unregisterListenersForThisClass() { 159 } 160 161 /** {@inheritDoc} */ 162 @Override 163 public void disposeMe() { 164 } 165 166 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TriggerOnce.class); 167 168}