001package jmri.jmrit.logixng.actions; 002 003import java.util.*; 004 005import jmri.InstanceManager; 006import jmri.JmriException; 007import jmri.jmrit.logixng.*; 008import jmri.jmrit.logixng.expressions.AbstractDigitalExpression; 009 010/** 011 * Executes actions in a sequence. 012 * 013 * @author Daniel Bergqvist Copyright 2020 014 */ 015public class Sequence extends AbstractDigitalAction 016 implements FemaleSocketListener { 017 018 private static class State { 019 private int _currentStep = -1; 020 private boolean _isRunning = false; 021 } 022 023 public static final int EXPRESSION_START = 0; 024 public static final int EXPRESSION_STOP = 1; 025 public static final int EXPRESSION_RESET = 2; 026 public static final int NUM_STATIC_EXPRESSIONS = 3; 027 028 private String _startExpressionSocketSystemName; 029 private String _stopExpressionSocketSystemName; 030 private String _resetExpressionSocketSystemName; 031 private final FemaleDigitalExpressionSocket _startExpressionSocket; 032 private final FemaleDigitalExpressionSocket _stopExpressionSocket; 033 private final FemaleDigitalExpressionSocket _resetExpressionSocket; 034 private final List<ExpressionEntry> _expressionEntries = new ArrayList<>(); 035 private final List<ActionEntry> _actionEntries = new ArrayList<>(); 036 private boolean _startImmediately = false; 037 private boolean _runContinuously = false; 038 private boolean disableCheckForUnconnectedSocket = false; 039 private final Map<ConditionalNG, State> _stateMap = new HashMap<>(); 040 041 public Sequence(String sys, String user) { 042 super(sys, user); 043 _startExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class) 044 .createFemaleSocket(this, this, Bundle.getMessage("SequenceSocketStart")); 045 _stopExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class) 046 .createFemaleSocket(this, this, Bundle.getMessage("SequenceSocketStop")); 047 _resetExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class) 048 .createFemaleSocket(this, this, Bundle.getMessage("SequenceSocketReset")); 049 _actionEntries 050 .add(new ActionEntry(InstanceManager.getDefault(DigitalActionManager.class) 051 .createFemaleSocket(this, this, getNewActionSocketName()))); 052 _expressionEntries 053 .add(new ExpressionEntry(InstanceManager.getDefault(DigitalExpressionManager.class) 054 .createFemaleSocket(this, this, getNewExpressionSocketName()))); 055 } 056 057 public Sequence(String sys, String user, 058 List<Map.Entry<String, String>> expressionSystemNames, 059 List<Map.Entry<String, String>> actionSystemNames) 060 throws BadUserNameException, BadSystemNameException { 061 super(sys, user); 062 _startExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class) 063 .createFemaleSocket(this, this, Bundle.getMessage("SequenceSocketStart")); 064 _stopExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class) 065 .createFemaleSocket(this, this, Bundle.getMessage("SequenceSocketStop")); 066 _resetExpressionSocket = InstanceManager.getDefault(DigitalExpressionManager.class) 067 .createFemaleSocket(this, this, Bundle.getMessage("SequenceSocketReset")); 068 setExpressionSystemNames(expressionSystemNames); 069 setActionSystemNames(actionSystemNames); 070 } 071 072 public String getNewActionSocketName() { 073 String[] names = new String[getChildCount()]; 074 for (int i=0; i < getChildCount(); i++) { 075 names[i] = getChild(i).getName(); 076 } 077 return getNewSocketName(names); 078 } 079 080 public String getNewExpressionSocketName() { 081 String[] names = new String[getChildCount()]; 082 for (int i=0; i < getChildCount(); i++) { 083 names[i] = getChild(i).getName(); 084 } 085 return AbstractDigitalExpression.getNewSocketName(names); 086 } 087 088 @Override 089 public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException { 090 DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class); 091 String sysName = systemNames.get(getSystemName()); 092 String userName = userNames.get(getSystemName()); 093 if (sysName == null) sysName = manager.getAutoSystemName(); 094 Sequence copy = new Sequence(sysName, userName); 095 copy.setComment(getComment()); 096 copy.setStartImmediately(_startImmediately); 097 copy.setRunContinuously(_runContinuously); 098 099 // Ensure the copy has as many childs as myself 100 while (copy.getChildCount() < this.getChildCount()) { 101 copy.doSocketOperation(copy.getChildCount()-1, FemaleSocketOperation.InsertAfter); 102 } 103 104 return manager.registerAction(copy).deepCopyChildren(this, systemNames, userNames); 105 } 106 107 private void setExpressionSystemNames(List<Map.Entry<String, String>> systemNames) { 108 if (!_expressionEntries.isEmpty()) { 109 throw new RuntimeException("expression system names cannot be set more than once"); 110 } 111 112 for (Map.Entry<String, String> entry : systemNames) { 113 FemaleDigitalExpressionSocket socket = 114 InstanceManager.getDefault(DigitalExpressionManager.class) 115 .createFemaleSocket(this, this, entry.getKey()); 116 117 _expressionEntries.add(new ExpressionEntry(socket, entry.getValue())); 118 } 119 } 120 121 private void setActionSystemNames(List<Map.Entry<String, String>> systemNames) { 122 if (!_actionEntries.isEmpty()) { 123 throw new RuntimeException("action system names cannot be set more than once"); 124 } 125 126 for (Map.Entry<String, String> entry : systemNames) { 127 FemaleDigitalActionSocket socket = 128 InstanceManager.getDefault(DigitalActionManager.class) 129 .createFemaleSocket(this, this, entry.getKey()); 130 131 _actionEntries.add(new ActionEntry(socket, entry.getValue())); 132 } 133 } 134 135 /** {@inheritDoc} */ 136 @Override 137 public Category getCategory() { 138 return Category.FLOW_CONTROL; 139 } 140 141 /** {@inheritDoc} */ 142 @Override 143 public void execute() throws JmriException { 144 State state = _stateMap.computeIfAbsent(getConditionalNG(), o -> new State()); 145 if (_startImmediately) state._isRunning = true; 146 147 // We want to limit the number of loops in case all expressions return 148 // True so we don't get caught in an endless loop 149 for (int count=0; count < _actionEntries.size(); count++) { 150 if (_stopExpressionSocket.isConnected() 151 && _stopExpressionSocket.evaluate()) { 152 state._isRunning = false; 153// System.out.format("Stop: _currentStep: %d%n", _currentStep); 154 return; 155 } 156 157 if (_startExpressionSocket.isConnected() 158 && _startExpressionSocket.evaluate()) { 159 state._isRunning = true; 160// System.out.format("Start: _currentStep: %d%n", _currentStep); 161 } 162 163 if (_resetExpressionSocket.isConnected() 164 && _resetExpressionSocket.evaluate()) { 165 state._currentStep = -1; 166// System.out.format("Reset: _currentStep: %d%n", _currentStep); 167 } 168 169 if (!state._isRunning) return; 170 171 if (state._currentStep == -1) { 172 state._currentStep = 0; 173// System.out.format("_currentStep: %d, size: %d%n", _currentStep, _actionEntries.size()); 174 FemaleDigitalActionSocket socket = 175 _actionEntries.get(state._currentStep)._socket; 176 if (socket.isConnected()) socket.execute(); 177 } 178 179 FemaleDigitalExpressionSocket exprSocket = 180 _expressionEntries.get(state._currentStep)._socket; 181 if (exprSocket.isConnected()) { 182 if (exprSocket.evaluate()) { 183 state._currentStep++; 184// System.out.format("_currentStep: %d, size: %d%n", _currentStep, _actionEntries.size()); 185 if (state._currentStep >= _actionEntries.size()) { 186 state._currentStep = 0; 187// System.out.format("_currentStep set to 0: %d%n", _currentStep); 188 } 189 190 FemaleDigitalActionSocket actionSocket = 191 _actionEntries.get(state._currentStep)._socket; 192 if (actionSocket.isConnected()) actionSocket.execute(); 193 194 if (!_runContinuously && state._currentStep == _actionEntries.size() - 1) { 195 // Sequence is done, stop and reset the sequence so that it can be started again later 196 state._isRunning = false; 197 state._currentStep = -1; 198 } 199 } else { 200 // Break the outer for loop 201 return; 202 } 203 } 204 } 205 } 206 207 /** 208 * Get if to start immediately 209 * @return true if to start immediately 210 */ 211 public boolean getStartImmediately() { 212 return _startImmediately; 213 } 214 215 /** 216 * Set if to start immediately 217 * @param startImmediately true if to start immediately 218 */ 219 public void setStartImmediately(boolean startImmediately) { 220 _startImmediately = startImmediately; 221 if (_startImmediately) { 222 _stateMap.forEach((conditionalNG, state) -> { state._isRunning = true; }); 223 } 224 } 225 226 /** 227 * Get if run continuously 228 * @return true if run continuously 229 */ 230 public boolean getRunContinuously() { 231 return _runContinuously; 232 } 233 234 /** 235 * Set if run continuously 236 * @param runContinuously true if run continuously 237 */ 238 public void setRunContinuously(boolean runContinuously) { 239 _runContinuously = runContinuously; 240 } 241 242 @Override 243 public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException { 244 if (index == EXPRESSION_START) return _startExpressionSocket; 245 if (index == EXPRESSION_STOP) return _stopExpressionSocket; 246 if (index == EXPRESSION_RESET) return _resetExpressionSocket; 247 248 index -= NUM_STATIC_EXPRESSIONS; 249 if ((index % 2) == 0) return _actionEntries.get(index >> 1)._socket; 250 else return _expressionEntries.get(index >> 1)._socket; 251 } 252 253 @Override 254 public int getChildCount() { 255 return NUM_STATIC_EXPRESSIONS + _expressionEntries.size() + _actionEntries.size(); 256 } 257 258 /** {@inheritDoc} */ 259 @Override 260 public boolean isSocketOperationAllowed(int index, FemaleSocketOperation oper) { 261 index -= NUM_STATIC_EXPRESSIONS; 262 263 // Num children except the static expressions 264 int numChilds = getChildCount() - NUM_STATIC_EXPRESSIONS; 265 266 switch (oper) { 267 case Remove: 268 // Possible if not the three static sockets, 269 // the socket is not connected and the next socket is not connected 270 return (index >= 0) 271 && (index+1 < numChilds) 272 && !getChild(index+NUM_STATIC_EXPRESSIONS).isConnected() 273 && !getChild(index+NUM_STATIC_EXPRESSIONS+1).isConnected(); 274 case InsertBefore: 275 // Possible if not the first three static sockets 276 return index >= 0; 277 case InsertAfter: 278 // Possible if not the static sockets, except the last one 279 return index >= -1; 280 case MoveUp: 281 // Possible, except for the the three static sockets, the first two sockets after that, and the last socket 282 return (index >= 2) && (index < numChilds-1); 283 case MoveDown: 284 // Possible if not the static sockets and if not the last three sockets 285 return (index >= 0) && (index < numChilds-3); 286 default: 287 throw new UnsupportedOperationException("Oper is unknown" + oper.name()); 288 } 289 } 290 291 private void insertNewSocket(int index) { 292 int actionIndex = index >> 1; 293 int expressionIndex = index >> 1; 294 295 // Does index points to an expression socket instead of an action socket? 296 if ((index % 2) != 0) { 297 expressionIndex = index >> 1; 298 actionIndex = (index >> 1) + 1; 299 } 300 301 FemaleDigitalActionSocket actionSocket = 302 InstanceManager.getDefault(DigitalActionManager.class) 303 .createFemaleSocket(this, this, getNewActionSocketName()); 304 _actionEntries.add(actionIndex, new ActionEntry(actionSocket)); 305 306 FemaleDigitalExpressionSocket exprSocket = 307 InstanceManager.getDefault(DigitalExpressionManager.class) 308 .createFemaleSocket(this, this, getNewExpressionSocketName()); 309 _expressionEntries.add(expressionIndex, new ExpressionEntry(exprSocket)); 310 311 List<FemaleSocket> addList = new ArrayList<>(); 312 addList.add(actionSocket); 313 addList.add(exprSocket); 314 firePropertyChange(Base.PROPERTY_CHILD_COUNT, null, addList); 315 } 316 317 private void removeSocket(int index) { 318 int actionIndex = index >> 1; 319 int expressionIndex = index >> 1; 320 321 // Does index points to an expression socket instead of an action socket? 322 if ((index % 2) != 0) { 323 actionIndex = (index >> 1) + 1; 324 } 325 326 List<FemaleSocket> removeList = new ArrayList<>(); 327 removeList.add(_actionEntries.remove(actionIndex)._socket); 328 removeList.add(_expressionEntries.remove(expressionIndex)._socket); 329 firePropertyChange(Base.PROPERTY_CHILD_COUNT, removeList, null); 330 } 331 332 private void moveSocketDown(int index) { 333 int actionIndex = index >> 1; 334 int expressionIndex = index >> 1; 335 336 // Does index points to an expression socket instead of an action socket? 337 if ((index % 2) != 0) { 338 actionIndex = (index >> 1) + 1; 339 } 340 341 ActionEntry actionTemp = _actionEntries.get(actionIndex); 342 _actionEntries.set(actionIndex, _actionEntries.get(actionIndex+1)); 343 _actionEntries.set(actionIndex+1, actionTemp); 344 345 ExpressionEntry exprTemp = _expressionEntries.get(expressionIndex); 346 _expressionEntries.set(expressionIndex, _expressionEntries.get(expressionIndex+1)); 347 _expressionEntries.set(expressionIndex+1, exprTemp); 348 349 List<FemaleSocket> list = new ArrayList<>(); 350 list.add(_actionEntries.get(actionIndex)._socket); 351 list.add(_actionEntries.get(actionIndex+1)._socket); 352 list.add(_expressionEntries.get(expressionIndex)._socket); 353 list.add(_expressionEntries.get(expressionIndex+1)._socket); 354 firePropertyChange(Base.PROPERTY_CHILD_REORDER, null, list); 355 } 356 357 /** {@inheritDoc} */ 358 @Override 359 public void doSocketOperation(int index, FemaleSocketOperation oper) { 360 index -= NUM_STATIC_EXPRESSIONS; 361 362 switch (oper) { 363 case Remove: 364 if (index+NUM_STATIC_EXPRESSIONS+1 >= getChildCount()) throw new UnsupportedOperationException("Cannot remove only the last socket"); 365 if (getChild(index+NUM_STATIC_EXPRESSIONS).isConnected()) throw new UnsupportedOperationException("Socket is connected"); 366 if (getChild(index+NUM_STATIC_EXPRESSIONS+1).isConnected()) throw new UnsupportedOperationException("Socket below is connected"); 367 removeSocket(index); 368 break; 369 case InsertBefore: 370 insertNewSocket(index); 371 break; 372 case InsertAfter: 373 insertNewSocket(index+1); 374 break; 375 case MoveUp: 376 if (index < 0) throw new UnsupportedOperationException("cannot move up static sockets"); 377 if (index <= 1) throw new UnsupportedOperationException("cannot move up first two children"); 378 moveSocketDown(index-2); 379 break; 380 case MoveDown: 381 if (index+2 >= getChildCount()) throw new UnsupportedOperationException("cannot move down last two children"); 382 moveSocketDown(index); 383 break; 384 default: 385 throw new UnsupportedOperationException("Oper is unknown" + oper.name()); 386 } 387 } 388 389 @Override 390 public void connected(FemaleSocket socket) { 391 if (disableCheckForUnconnectedSocket) return; 392 393 if (socket == _startExpressionSocket) { 394 _startExpressionSocketSystemName = socket.getConnectedSocket().getSystemName(); 395 } else if (socket == _stopExpressionSocket) { 396 _stopExpressionSocketSystemName = socket.getConnectedSocket().getSystemName(); 397 } else if (socket == _resetExpressionSocket) { 398 _resetExpressionSocketSystemName = socket.getConnectedSocket().getSystemName(); 399 } else { 400 for (ExpressionEntry entry : _expressionEntries) { 401 if (socket == entry._socket) { 402 entry._socketSystemName = 403 socket.getConnectedSocket().getSystemName(); 404 } 405 } 406 for (ActionEntry entry : _actionEntries) { 407 if (socket == entry._socket) { 408 entry._socketSystemName = 409 socket.getConnectedSocket().getSystemName(); 410 } 411 } 412 } 413 } 414 415 @Override 416 public void disconnected(FemaleSocket socket) { 417 if (socket == _startExpressionSocket) { 418 _startExpressionSocketSystemName = null; 419 } else if (socket == _stopExpressionSocket) { 420 _stopExpressionSocketSystemName = null; 421 } else if (socket == _resetExpressionSocket) { 422 _resetExpressionSocketSystemName = null; 423 } else { 424 for (ExpressionEntry entry : _expressionEntries) { 425 if (socket == entry._socket) { 426 entry._socketSystemName = null; 427 } 428 } 429 for (ActionEntry entry : _actionEntries) { 430 if (socket == entry._socket) { 431 entry._socketSystemName = null; 432 } 433 } 434 } 435 } 436 437 @Override 438 public String getShortDescription(Locale locale) { 439 return Bundle.getMessage(locale, "Sequence_Short"); 440 } 441 442 @Override 443 public String getLongDescription(Locale locale) { 444 return Bundle.getMessage(locale, "Sequence_Long"); 445 } 446 447 public FemaleDigitalExpressionSocket getStartExpressionSocket() { 448 return _startExpressionSocket; 449 } 450 451 public String getStartExpressionSocketSystemName() { 452 return _startExpressionSocketSystemName; 453 } 454 455 public void setStartExpressionSocketSystemName(String systemName) { 456 _startExpressionSocketSystemName = systemName; 457 } 458 459 public FemaleDigitalExpressionSocket getStopExpressionSocket() { 460 return _stopExpressionSocket; 461 } 462 463 public String getStopExpressionSocketSystemName() { 464 return _stopExpressionSocketSystemName; 465 } 466 467 public void setStopExpressionSocketSystemName(String systemName) { 468 _stopExpressionSocketSystemName = systemName; 469 } 470 471 public FemaleDigitalExpressionSocket getResetExpressionSocket() { 472 return _resetExpressionSocket; 473 } 474 475 public String getResetExpressionSocketSystemName() { 476 return _resetExpressionSocketSystemName; 477 } 478 479 public void setResetExpressionSocketSystemName(String systemName) { 480 _resetExpressionSocketSystemName = systemName; 481 } 482 483 public int getNumExpressions() { 484 return _expressionEntries.size(); 485 } 486 487 public FemaleDigitalExpressionSocket getExpressionSocket(int socket) { 488 return _expressionEntries.get(socket)._socket; 489 } 490 491 public String getExpressionSocketSystemName(int socket) { 492 return _expressionEntries.get(socket)._socketSystemName; 493 } 494 495 public void setExpressionSocketSystemName(int socket, String systemName) { 496 _expressionEntries.get(socket)._socketSystemName = systemName; 497 } 498 499 public int getNumActions() { 500 return _actionEntries.size(); 501 } 502 503 public FemaleDigitalActionSocket getActionSocket(int socket) { 504 return _actionEntries.get(socket)._socket; 505 } 506 507 public String getActionSocketSystemName(int socket) { 508 return _actionEntries.get(socket)._socketSystemName; 509 } 510 511 public void setActionSocketSystemName(int socket, String systemName) { 512 _actionEntries.get(socket)._socketSystemName = systemName; 513 } 514 515 /** {@inheritDoc} */ 516 @Override 517 public void setup() { 518 // We don't want to check for unconnected sockets while setup sockets 519 disableCheckForUnconnectedSocket = true; 520 521 try { 522 if ( !_startExpressionSocket.isConnected() 523 || !_startExpressionSocket.getConnectedSocket().getSystemName() 524 .equals(_startExpressionSocketSystemName)) { 525 526 String socketSystemName = _startExpressionSocketSystemName; 527 _startExpressionSocket.disconnect(); 528 if (socketSystemName != null) { 529 MaleSocket maleSocket = 530 InstanceManager.getDefault(DigitalExpressionManager.class) 531 .getBySystemName(socketSystemName); 532 if (maleSocket != null) { 533 _startExpressionSocket.connect(maleSocket); 534 maleSocket.setup(); 535 } else { 536 log.error("cannot load digital expression {}", socketSystemName); 537 } 538 } 539 } else { 540 _startExpressionSocket.getConnectedSocket().setup(); 541 } 542 543 if ( !_stopExpressionSocket.isConnected() 544 || !_stopExpressionSocket.getConnectedSocket().getSystemName() 545 .equals(_stopExpressionSocketSystemName)) { 546 547 String socketSystemName = _stopExpressionSocketSystemName; 548 _stopExpressionSocket.disconnect(); 549 if (socketSystemName != null) { 550 MaleSocket maleSocket = 551 InstanceManager.getDefault(DigitalExpressionManager.class) 552 .getBySystemName(socketSystemName); 553 _stopExpressionSocket.disconnect(); 554 if (maleSocket != null) { 555 _stopExpressionSocket.connect(maleSocket); 556 maleSocket.setup(); 557 } else { 558 log.error("cannot load digital expression {}", socketSystemName); 559 } 560 } 561 } else { 562 _stopExpressionSocket.getConnectedSocket().setup(); 563 } 564 565 if ( !_resetExpressionSocket.isConnected() 566 || !_resetExpressionSocket.getConnectedSocket().getSystemName() 567 .equals(_resetExpressionSocketSystemName)) { 568 569 String socketSystemName = _resetExpressionSocketSystemName; 570 _resetExpressionSocket.disconnect(); 571 if (socketSystemName != null) { 572 MaleSocket maleSocket = 573 InstanceManager.getDefault(DigitalExpressionManager.class) 574 .getBySystemName(socketSystemName); 575 _resetExpressionSocket.disconnect(); 576 if (maleSocket != null) { 577 _resetExpressionSocket.connect(maleSocket); 578 maleSocket.setup(); 579 } else { 580 log.error("cannot load digital expression {}", socketSystemName); 581 } 582 } 583 } else { 584 _resetExpressionSocket.getConnectedSocket().setup(); 585 } 586 587 for (ExpressionEntry ee : _expressionEntries) { 588 if ( !ee._socket.isConnected() 589 || !ee._socket.getConnectedSocket().getSystemName() 590 .equals(ee._socketSystemName)) { 591 592 String socketSystemName = ee._socketSystemName; 593 ee._socket.disconnect(); 594 if (socketSystemName != null) { 595 MaleSocket maleSocket = 596 InstanceManager.getDefault(DigitalExpressionManager.class) 597 .getBySystemName(socketSystemName); 598 ee._socket.disconnect(); 599 if (maleSocket != null) { 600 ee._socket.connect(maleSocket); 601 maleSocket.setup(); 602 } else { 603 log.error("cannot load digital expression {}", socketSystemName); 604 } 605 } 606 } else { 607 ee._socket.getConnectedSocket().setup(); 608 } 609 } 610 611 for (ActionEntry ae : _actionEntries) { 612 if ( !ae._socket.isConnected() 613 || !ae._socket.getConnectedSocket().getSystemName() 614 .equals(ae._socketSystemName)) { 615 616 String socketSystemName = ae._socketSystemName; 617 ae._socket.disconnect(); 618 if (socketSystemName != null) { 619 MaleSocket maleSocket = 620 InstanceManager.getDefault(DigitalActionManager.class) 621 .getBySystemName(socketSystemName); 622 ae._socket.disconnect(); 623 if (maleSocket != null) { 624 ae._socket.connect(maleSocket); 625 maleSocket.setup(); 626 } else { 627 log.error("cannot load digital action {}", socketSystemName); 628 } 629 } 630 } else { 631 ae._socket.getConnectedSocket().setup(); 632 } 633 } 634 } catch (SocketAlreadyConnectedException ex) { 635 // This shouldn't happen and is a runtime error if it does. 636 throw new RuntimeException("socket is already connected"); 637 } 638 639 disableCheckForUnconnectedSocket = false; 640 } 641 642 /** {@inheritDoc} */ 643 @Override 644 public void registerListenersForThisClass() { 645 if (!_listenersAreRegistered) { 646 _listenersAreRegistered = true; 647 } 648 } 649 650 /** {@inheritDoc} */ 651 @Override 652 public void unregisterListenersForThisClass() { 653 _listenersAreRegistered = false; 654 } 655 656 /** {@inheritDoc} */ 657 @Override 658 public void disposeMe() { 659 } 660 661 662 private static class ExpressionEntry { 663 private String _socketSystemName; 664 private final FemaleDigitalExpressionSocket _socket; 665 666 private ExpressionEntry(FemaleDigitalExpressionSocket socket, String socketSystemName) { 667 _socketSystemName = socketSystemName; 668 _socket = socket; 669 } 670 671 private ExpressionEntry(FemaleDigitalExpressionSocket socket) { 672 this._socket = socket; 673 } 674 675 } 676 677 private static class ActionEntry { 678 private String _socketSystemName; 679 private final FemaleDigitalActionSocket _socket; 680 681 private ActionEntry(FemaleDigitalActionSocket socket, String socketSystemName) { 682 _socketSystemName = socketSystemName; 683 _socket = socket; 684 } 685 686 private ActionEntry(FemaleDigitalActionSocket socket) { 687 this._socket = socket; 688 } 689 690 } 691 692 693 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Sequence.class); 694 695}