001package jmri.jmrix.ecos; 002 003import java.awt.Component; 004import java.awt.event.ActionEvent; 005import java.awt.event.ActionListener; 006import java.util.ArrayList; 007import java.util.Enumeration; 008import java.util.Hashtable; 009import java.util.List; 010import java.util.ResourceBundle; 011 012import javax.annotation.Nonnull; 013import javax.swing.BorderFactory; 014import javax.swing.BoxLayout; 015import javax.swing.JButton; 016import javax.swing.JCheckBox; 017import javax.swing.JDialog; 018import javax.swing.JLabel; 019import javax.swing.JPanel; 020 021import jmri.*; 022import jmri.jmrix.ecos.utilities.GetEcosObjectNumber; 023import jmri.jmrix.ecos.utilities.RemoveObjectFromEcos; 024import jmri.util.swing.JmriJOptionPane; 025 026/** 027 * Implement turnout manager for Ecos systems. 028 * <p> 029 * System names are "UTnnn", where U is the user configurable system prefix, 030 * nnn is the turnout number without padding. 031 * 032 * @author Bob Jacobsen Copyright (C) 2001, 2008 033 */ 034public class EcosTurnoutManager extends jmri.managers.AbstractTurnoutManager 035 implements EcosListener { 036 037 public EcosTurnoutManager(EcosSystemConnectionMemo memo) { 038 super(memo); 039 initEtm(); 040 } 041 042 private void initEtm() { 043 tc = getMemo().getTrafficController(); 044 045 // listen for turnout creation 046 // connect to the TrafficManager 047 tc.addEcosListener(this); 048 049 // ask to be notified about newly created turnouts on the layout. 050 EcosMessage m = new EcosMessage("request(11, view)"); 051 tc.sendEcosMessage(m, this); 052 053 // get initial state 054 m = new EcosMessage("queryObjects(11, addrext)"); 055 tc.sendEcosMessage(m, this); 056 this.addPropertyChangeListener(this); 057 } 058 059 EcosTrafficController tc; 060 061 // The hash table simply holds the object number against the EcosTurnout ref. 062 private final Hashtable<Integer, EcosTurnout> _tecos = new Hashtable<>(); // stores known Ecos Object ids to DCC 063 064 /** 065 * {@inheritDoc} 066 */ 067 @Override 068 @Nonnull 069 public EcosSystemConnectionMemo getMemo() { 070 return (EcosSystemConnectionMemo) memo; 071 } 072 073 /** 074 * {@inheritDoc} 075 */ 076 @Nonnull 077 @Override 078 protected Turnout createNewTurnout(@Nonnull String systemName, String userName) throws IllegalArgumentException { 079 int addr; 080 try { 081 addr = Integer.parseInt(systemName.substring(getSystemNamePrefix().length())); 082 } catch (NumberFormatException e) { 083 throw new IllegalArgumentException("failed to convert systemName '"+systemName+"' to an Ecos turnout address"); 084 } 085 Turnout t = new EcosTurnout(addr, getSystemPrefix(), tc, this); 086 t.setUserName(userName); 087 t.setFeedbackMode("MONITORING"); 088 return t; 089 } 090 091 @Override 092 public boolean allowMultipleAdditions(@Nonnull String systemName) { 093 return true; 094 } 095 096 // to listen for status changes from Ecos system 097 @Override 098 public void reply(EcosReply m) { 099 log.debug("reply {}", m); 100 // is this a list of turnouts? 101 EcosTurnout et; 102 103 if (m.getResultCode() == 0) { 104 int ecosObjectId = m.getEcosObjectId(); 105 if ((ecosObjectId != 11) && ((ecosObjectId < 20000) || (ecosObjectId > 30000))) { 106 log.debug("message received that is not within the valid turnout object range"); 107 return; 108 } 109 List<String> headerDetails = m.getReplyHeaderDetails(); 110 String[] msgContents = m.getContents(); 111 //log.info("Initial Header " + headerDetails); 112 if (m.isUnsolicited()) { 113 if (ecosObjectId == 11) { 114 //Creation or removal of a turnout from the Ecos. 115 if (msgContents[0].contains("msg[LIST_CHANGED]")) { 116 log.debug("We have received notification of a change in the Turnout list"); 117 EcosMessage mout = new EcosMessage("queryObjects(11)"); 118 tc.sendEcosMessage(mout, this); 119 } 120 //Creation or removal of a turnout from the Ecos. 121 } else { 122 log.debug("Forwarding on State change for {}", ecosObjectId); 123 et = _tecos.get(ecosObjectId); 124 if (et != null) { 125 et.reply(m); 126 //As the event will come from one object, we shall check to see if it is an extended address, 127 // if it is we also forward the message onto the slaved address. 128 if (et.getExtended() != 0) { 129 log.debug("This is also an extended turnout so forwarding on change to {}", et.getSlaveAddress()); 130 EcosTurnout etx = (EcosTurnout) provideTurnout(et.getSlaveAddress()); 131 etx.reply(m); 132 } 133 } 134 } 135 136 } else { 137 String replyType = m.getReplyType(); 138 if (replyType.equals("queryObjects")) { 139 if (ecosObjectId == 11 && headerDetails.size() == 0) { 140 //if (lines[0].startsWith("<REPLY queryObjects(11)>")) { 141 log.debug("No sub details"); 142 checkTurnoutList(msgContents); 143 } else if (headerDetails.contains("addr")) { 144 // yes, make sure TOs exist 145 //log.debug("found "+(lines.length-2)+" turnout objects"); 146 for (String item : m.getContents()) { 147 log.debug("header {}", item); 148 //for (int i = 1; i<lines.length-1; i++) { 149 if (item.contains("addr")) { // skip odd lines 150 int object = GetEcosObjectNumber.getEcosObjectNumber(item, null, " "); 151 if ((20000 <= object) && (object < 30000)) { // only physical turnouts 152 int addr = GetEcosObjectNumber.getEcosObjectNumber(item, "[", "]"); 153 log.debug("Found turnout object {} addr {}", object, addr); 154 155 if (addr > 0) { 156 Turnout t = getTurnout(getSystemNamePrefix() + addr); 157 if (t == null) { 158 et = (EcosTurnout) provideTurnout(getSystemNamePrefix() + addr); 159 et.setObjectNumber(object); 160 _tecos.put(object, et); 161 } 162 } 163 } else if ((30000 <= object) && (object < 40000)) { //This is a ecos route 164 log.debug("Found route object {}", object); 165 166 Turnout t = getTurnout(getSystemNamePrefix() + object); 167 if (t == null) { 168 et = (EcosTurnout) provideTurnout(getSystemNamePrefix() + object); 169 et.setObjectNumber(object); 170 _tecos.put(object, et); 171 } 172 } 173 if ((20000 <= object) && (object < 40000)) { 174 EcosMessage em = new EcosMessage("request(" + object + ",view)"); 175 tc.sendEcosMessage(em, this); 176 em = new EcosMessage("get(" + object + ",state)"); 177 tc.sendEcosMessage(em, this); 178 } 179 } 180 } 181 } else if (headerDetails.contains("addrext")) { 182 //log.info("Extended"); 183 for (String item : m.getContents()) { 184 //log.info(item); 185 if (item.contains("addrext")) { // skip odd lines 186 turnoutAddressDetails(item); 187 } 188 } 189 } 190 } else if (replyType.equals("get")) { 191 et = (EcosTurnout) getByEcosObject(ecosObjectId); 192 if (headerDetails.contains("state")) { 193 //As this is in response to a change in state we shall forward 194 //it straight on to the ecos turnout to deal with. 195 et.reply(m); 196 //As the event will come from one object, we shall check to see if it is an extended address, 197 // if it is we also forward the message onto the slaved address. 198 if (et.getExtended() != 0) { 199 EcosTurnout etx = (EcosTurnout) provideTurnout(et.getSlaveAddress()); 200 etx.reply(m); 201 } 202 203 } else if (headerDetails.contains("symbol")) { 204 //Extract symbol number and set on turnout. 205 int symbol = GetEcosObjectNumber.getEcosObjectNumber(msgContents[0], "[", "]"); 206 et.setExtended(symbol); 207 et.setTurnoutOperation(jmri.InstanceManager.getDefault(TurnoutOperationManager.class).getOperation("NoFeedback")); 208 if ((symbol == 2) || (symbol == 4)) { 209 210 EcosTurnout etx = (EcosTurnout) provideTurnout(et.getSlaveAddress()); 211 etx.setExtended(symbol); 212 etx.setTurnoutOperation(jmri.InstanceManager.getDefault(TurnoutOperationManager.class).getOperation("NoFeedback")); 213 switch (symbol) { 214 case 2: 215 et.setComment("Three Way Point with " + et.getSlaveAddress()); 216 break; 217 case 4: 218 et.setComment("Double Slip with " + et.getSlaveAddress()); 219 break; 220 default: 221 break; 222 } 223 } 224 // get initial state 225 EcosMessage em = new EcosMessage("get(" + ecosObjectId + ",state)"); 226 tc.sendEcosMessage(em, this); 227 228 } else if (headerDetails.contains("addrext")) { 229 turnoutAddressDetails(msgContents[0]); 230 } else { 231 String name = null; 232 for (String li : msgContents) { 233 if (li.contains("name")) { 234 //start=li.indexOf("[")+2; 235 //end=li.indexOf("]")-1; 236 if ((name != null) /*&& (start!=end)*/) { 237 name = name + EcosReply.getContentDetail(li); /*" " + li.substring(start, end);*/ 238 239 } else { 240 name = EcosReply.getContentDetail(li); /*li.substring(start, end);*/ 241 242 } 243 } 244 } 245 if (name != null) { 246 et.setUserName(name); 247 } 248 } 249 } else if (ecosObjectId >= 20000) { // ecosObjectId <= 30000 is always true at this point (Spotbugs) 250 log.debug("Reply for specific turnout"); 251 et = _tecos.get(ecosObjectId); 252 if (et != null) { 253 et.reply(m); 254 //As the event will come from one object, we shall check to see if it is an extended address, 255 // if it is we also forward the message onto the slaved address. 256 if (et.getExtended() != 0) { 257 log.debug("This is also an extended turnout so forwarding on change to {}", et.getSlaveAddress()); 258 EcosTurnout etx = (EcosTurnout) provideTurnout(et.getSlaveAddress()); 259 etx.reply(m); 260 } 261 } 262 } 263 } 264 } else { 265 log.debug("Message received from Ecos is in error"); 266 } 267 } 268 269 protected boolean addingTurnouts = false; 270 271 private void turnoutAddressDetails(String lines) { 272 addingTurnouts = true; 273 EcosTurnout et; 274 int start; 275 int end; 276 int object = GetEcosObjectNumber.getEcosObjectNumber(lines, null, " "); 277 if ((20000 <= object) && (object < 30000)) { 278 start = lines.indexOf('[') + 1; 279 end = lines.indexOf(']'); 280 String turnoutadd = stripChar(lines.substring(start, end)); 281 String[] straddr = turnoutadd.split(","); 282 log.debug("Number of Address for this device is {}", straddr.length); 283 if (straddr.length <= 2) { 284 if (straddr.length == 2) { 285 if (!straddr[0].equals(straddr[1])) { 286 log.debug("Addresses are not the same, we shall use the first address listed."); 287 } 288 } 289 int addr = Integer.parseInt(straddr[0]); 290 if (addr > 0) { 291 Turnout t = getTurnout(getSystemNamePrefix() + addr); 292 if (t == null) { 293 et = (EcosTurnout) provideTurnout(getSystemNamePrefix() + addr); 294 et.setObjectNumber(object); 295 _tecos.put(object, et); 296 // listen for changes 297 EcosMessage em = new EcosMessage("request(" + object + ",view)"); 298 tc.sendEcosMessage(em, this); 299 300 // get initial state 301 em = new EcosMessage("get(" + object + ",state)"); 302 tc.sendEcosMessage(em, this); 303 304 em = new EcosMessage("get(" + object + ", name1, name2, name3)"); 305 tc.sendEcosMessage(em, this); 306 } 307 } 308 309 } else if (straddr.length == 4) { 310 log.debug("We have a two address object."); 311 //The first two addresses should be the same 312 if (!straddr[0].equals(straddr[1])) { 313 log.debug("First Pair of Addresses are not the same, we shall use the first address"); 314 } 315 if (!straddr[2].equals(straddr[3])) { 316 log.debug("Second Pair of Addresses are not the same, we shall use the first address"); 317 } 318 int addr = Integer.parseInt(straddr[0]); 319 int addr2 = Integer.parseInt(straddr[2]); 320 if (addr > 0) { 321 //addr = straddr[0]; 322 Turnout t = getTurnout(getSystemNamePrefix() + addr); 323 if (t == null) { 324 et = (EcosTurnout) provideTurnout(getSystemNamePrefix() + addr); 325 et.setObjectNumber(object); 326 et.setSlaveAddress(addr2); 327 _tecos.put(object, et); 328 329 //Get the type of accessory... 330 EcosMessage em = new EcosMessage("get(" + object + ",symbol)"); 331 tc.sendEcosMessage(em, this); 332 333 // listen for changes 334 em = new EcosMessage("request(" + object + ",view)"); 335 tc.sendEcosMessage(em, this); 336 337 em = new EcosMessage("get(" + object + ", name1, name2, name3)"); 338 tc.sendEcosMessage(em, this); 339 } 340 } 341 342 if (addr2 > 0) { 343 Turnout t = getTurnout(getSystemNamePrefix() + addr2); 344 if (t == null) { 345 et = (EcosTurnout) provideTurnout(getSystemNamePrefix() + addr2); 346 et.setMasterObjectNumber(false); 347 et.setObjectNumber(object); 348 et.setComment("Extended address linked with turnout " + getSystemPrefix() + "T" + straddr[0]); 349 } 350 } 351 } 352 353 } else if ((30000 <= object) && (object < 40000)) { //This is a ecos route 354 355 log.debug("Found route object {}", object); 356 357 Turnout t = getTurnout(getSystemNamePrefix() + object); 358 if (t == null) { 359 et = (EcosTurnout) provideTurnout(getSystemNamePrefix() + object); 360 et.setObjectNumber(object); 361 _tecos.put(object, et); 362 363 // get initial state 364 EcosMessage em = new EcosMessage("get(" + object + ",state)"); 365 tc.sendEcosMessage(em, this); 366 //Need to do some more work on routes on the ecos. 367 368 // listen for changes 369 // em = new EcosMessage("request("+object+",view)"); 370 // tc.sendEcosMessage(em, null); 371 // get the name from the ecos to set as Username 372 em = new EcosMessage("get(" + object + ", name1, name2, name3)"); 373 tc.sendEcosMessage(em, this); 374 } 375 } 376 addingTurnouts = false; 377 } 378 379 /* This is used after an event update form the ecos informing us of a change in the 380 * turnout list, we have to determine if it is an addition or delete. 381 * We should only ever do either a remove or an add in one go. 382 */ 383 void checkTurnoutList(String[] ecoslines) { 384 final EcosPreferences p = getMemo().getPreferenceManager(); 385 386 String[] jmrilist = getEcosObjectArray(); 387 boolean nomatch = true; 388 int intTurnout = 0; 389 String strECOSTurnout = null; 390 for (int i = 0; i < jmrilist.length; i++) { 391 nomatch = true; 392 String strJMRITurnout = jmrilist[i]; 393 intTurnout = Integer.parseInt(strJMRITurnout); 394 for (String li : ecoslines) { 395 strECOSTurnout = li.replaceAll("[\\n\\r]", ""); 396 if (strECOSTurnout.equals(strJMRITurnout)) { 397 nomatch = false; 398 break; 399 } 400 } 401 402 if (nomatch) { 403 final EcosTurnout et = (EcosTurnout) getByEcosObject(intTurnout); 404 _tecos.remove(intTurnout); 405 if (p.getRemoveTurnoutsFromJMRI() == 0x02) { 406 //Remove turnout 407 _tecos.remove(et.getObject()); 408 deregister(et); 409 } else if (p.getRemoveTurnoutsFromJMRI() == 0x00) { 410 final JDialog dialog = new JDialog(); 411 dialog.setTitle(Bundle.getMessage("DeleteTurnoutTitle")); 412 dialog.setLocationRelativeTo(null); 413 dialog.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); 414 JPanel container = new JPanel(); 415 container.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 416 container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS)); 417 418 JLabel question = new JLabel(Bundle.getMessage("RemoveTurnoutLine1", et.getDisplayName())); 419 question.setAlignmentX(Component.CENTER_ALIGNMENT); 420 container.add(question); 421 question = new JLabel(Bundle.getMessage("RemoveTurnoutLine2")); 422 question.setAlignmentX(Component.CENTER_ALIGNMENT); 423 container.add(question); 424 final JCheckBox remember = new JCheckBox(Bundle.getMessage("MessageRememberSetting")); 425 remember.setFont(remember.getFont().deriveFont(10f)); 426 remember.setAlignmentX(Component.CENTER_ALIGNMENT); 427 428 JButton yesButton = new JButton(Bundle.getMessage("ButtonYes")); 429 JButton noButton = new JButton(Bundle.getMessage("ButtonNo")); 430 JPanel button = new JPanel(); 431 button.setAlignmentX(Component.CENTER_ALIGNMENT); 432 button.add(yesButton); 433 button.add(noButton); 434 container.add(button); 435 436 noButton.addActionListener(new ActionListener() { 437 @Override 438 public void actionPerformed(ActionEvent e) { 439 if (remember.isSelected()) { 440 p.setRemoveTurnoutsFromJMRI(0x01); 441 } 442 dialog.dispose(); 443 } 444 }); 445 446 yesButton.addActionListener(new ActionListener() { 447 final ResourceBundle rb = ResourceBundle.getBundle("jmri.jmrit.beantable.BeanTableBundle"); 448 449 @Override 450 public void actionPerformed(ActionEvent e) { 451 if (remember.isSelected()) { 452 p.setRemoveTurnoutsFromJMRI(0x02); 453 } 454 int count = et.getNumPropertyChangeListeners() - 1; // one is this table 455 if (log.isDebugEnabled()) { 456 log.debug("Delete with {}", count); 457 } 458 if ((!noWarnDelete) && (count > 0)) { 459 String msg = java.text.MessageFormat.format( 460 rb.getString("DeletePrompt") + "\n" 461 + rb.getString("ReminderInUse"), 462 new Object[]{et.getSystemName(), "" + count}); 463 // verify deletion 464 int val = JmriJOptionPane.showOptionDialog(null, 465 msg, Bundle.getMessage("WarningTitle"), 466 JmriJOptionPane.DEFAULT_OPTION, JmriJOptionPane.QUESTION_MESSAGE, null, 467 new Object[]{Bundle.getMessage("ButtonYes"), 468 rb.getString("ButtonYesPlus"), 469 Bundle.getMessage("ButtonNo")}, 470 Bundle.getMessage("ButtonNo")); 471 if (val == 2 || val == JmriJOptionPane.CLOSED_OPTION ) { // array position 2 472 _tecos.remove(et.getObject()); 473 deregister(et); 474 dialog.dispose(); 475 return; // return without deleting 476 } 477 if (val == 1) { // suppress future warnings 478 noWarnDelete = true; 479 } 480 } 481 // finally OK, do the actual delete 482 deleteEcosTurnout(et); 483 dialog.dispose(); 484 } 485 }); 486 container.add(remember); 487 container.setAlignmentX(Component.CENTER_ALIGNMENT); 488 container.setAlignmentY(Component.CENTER_ALIGNMENT); 489 dialog.getContentPane().add(container); 490 dialog.pack(); 491 dialog.setModal(true); 492 dialog.setVisible(true); 493 } else { 494 //We will need to remove the turnout from our list as it no longer exists on the ecos. 495 _tecos.remove(et.getObject()); 496 } 497 } 498 } 499 int turnout; 500 for (String li : ecoslines) { 501 String tmpturn = li.replaceAll("[\\n\\r]", ""); 502 turnout = Integer.parseInt(tmpturn); 503 if (getByEcosObject(turnout) == null) { 504 EcosMessage mout = new EcosMessage("get(" + turnout + ", addrext)"); 505 tc.sendEcosMessage(mout, this); 506 } 507 } 508 } 509 510 private boolean noWarnDelete = false; 511 512 public String stripChar(String s) { 513 String allowed 514 = ",0123456789"; 515 StringBuilder result = new StringBuilder(); 516 for (int i = 0; i < s.length(); i++) { 517 if (allowed.indexOf(s.charAt(i)) >= 0) { 518 result.append(s.charAt(i)); 519 } 520 } 521 522 return result.toString(); 523 } 524 525 @Override 526 public void message(EcosMessage m) { 527 // messages are ignored 528 } 529 530 @Override 531 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "UCF_USELESS_CONTROL_FLOW", 532 justification = "OK to compare floats, as even tiny differences should trigger update") 533 public void propertyChange(java.beans.PropertyChangeEvent e) { 534 if ((e.getPropertyName().equals("length")) && (!addingTurnouts)) { 535 final EcosPreferences p = getMemo().getPreferenceManager(); 536 EcosTurnout et; 537 String[] ecoslist = this.getEcosObjectArray(); 538 539 for (Turnout turnout : getNamedBeanSet()) { 540 if (turnout.getSystemName().startsWith(getSystemNamePrefix())) { 541 et = (EcosTurnout) turnout; 542 if (et.getObject() == 0) { 543 //We do not support this yet at there are many parameters 544 // when creating a turnout on the ecos. 545 } 546 } 547 } 548 549 for (int i = 0; i < ecoslist.length; i++) { 550 et = (EcosTurnout) getByEcosObject(Integer.parseInt(ecoslist[i])); 551 int address = et.getNumber(); 552 if (getBySystemName(getSystemNamePrefix() + address) == null) { 553 if (p.getRemoveTurnoutsFromEcos() == 0x02) { 554 RemoveObjectFromEcos removeObjectFromEcos = new RemoveObjectFromEcos(); 555 removeObjectFromEcos.removeObjectFromEcos("" + et.getObject(), tc); 556 deleteEcosTurnout(et); 557 } else { 558 final EcosTurnout etd = et; 559 final JDialog dialog = new JDialog(); 560 dialog.setTitle(Bundle.getMessage("RemoveTurnoutTitle")); 561 dialog.setLocation(300, 200); 562 dialog.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); 563 JPanel container = new JPanel(); 564 container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS)); 565 container.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 566 567 JLabel question = new JLabel(Bundle.getMessage("RemoveTurnoutX", etd.getSystemName())); 568 question.setAlignmentX(Component.CENTER_ALIGNMENT); 569 container.add(question); 570 final JCheckBox remember = new JCheckBox(Bundle.getMessage("MessageRememberSetting")); 571 remember.setFont(remember.getFont().deriveFont(10f)); 572 remember.setAlignmentX(Component.CENTER_ALIGNMENT); 573 remember.setVisible(true); 574 JButton yesButton = new JButton(Bundle.getMessage("ButtonYes")); 575 JButton noButton = new JButton(Bundle.getMessage("ButtonNo")); 576 JPanel button = new JPanel(); 577 button.setAlignmentX(Component.CENTER_ALIGNMENT); 578 button.add(yesButton); 579 button.add(noButton); 580 container.add(button); 581 582 noButton.addActionListener(new ActionListener() { 583 @Override 584 public void actionPerformed(ActionEvent e) { 585 if (remember.isSelected()) { 586 p.setRemoveTurnoutsFromEcos(0x01); 587 } 588 dialog.dispose(); 589 } 590 }); 591 592 yesButton.addActionListener(new ActionListener() { 593 @Override 594 public void actionPerformed(ActionEvent e) { 595 if (remember.isSelected()) { 596 p.setRemoveTurnoutsFromEcos(0x02); 597 } 598 RemoveObjectFromEcos removeObjectFromEcos = new RemoveObjectFromEcos(); 599 removeObjectFromEcos.removeObjectFromEcos("" + etd.getObject(), tc); 600 deleteEcosTurnout(etd); 601 dialog.dispose(); 602 } 603 }); 604 container.add(remember); 605 container.setAlignmentX(Component.CENTER_ALIGNMENT); 606 container.setAlignmentY(Component.CENTER_ALIGNMENT); 607 dialog.getContentPane().add(container); 608 dialog.pack(); 609 dialog.setModal(true); 610 dialog.setVisible(true); 611 } 612 } 613 } 614 } 615 super.propertyChange(e); 616 } 617 618 public void deleteEcosTurnout(EcosTurnout et) { 619 addingTurnouts = true; 620 deregister(et); 621 et.dispose(); 622 EcosMessage em = new EcosMessage("release(" + et.getObject() + ",view)"); 623 tc.sendEcosMessage(em, this); 624 _tecos.remove(Integer.valueOf(et.getObject())); 625 addingTurnouts = false; 626 } 627 628 @Override 629 public void dispose() { 630 Enumeration<Integer> en = _tecos.keys(); 631 EcosMessage em; 632 while (en.hasMoreElements()) { 633 int ecosObject = en.nextElement(); 634 em = new EcosMessage("release(" + ecosObject + ",view)"); 635 tc.sendEcosMessage(em, this); 636 } 637 638 if (InstanceManager.getNullableDefault(ConfigureManager.class) != null) { 639 InstanceManager.getDefault(ConfigureManager.class).deregister(this); 640 } 641 _tecos.clear(); 642 tc.removeEcosListener(this); // disconnect from tc 643 super.dispose(); // remove SensorManager and SystemConnectionMemo change listeners 644 } 645 646 public List<String> getEcosObjectList() { 647 String[] arr = new String[_tecos.size()]; 648 List<String> out = new ArrayList<String>(); 649 Enumeration<Integer> en = _tecos.keys(); 650 int i = 0; 651 while (en.hasMoreElements()) { 652 arr[i] = "" + en.nextElement(); 653 i++; 654 } 655 java.util.Arrays.sort(arr); 656 for (i = 0; i < arr.length; i++) { 657 out.add(arr[i]); 658 } 659 return out; 660 } 661 662 public String[] getEcosObjectArray() { 663 String[] arr = new String[_tecos.size()]; 664 Enumeration<Integer> en = _tecos.keys(); 665 int i = 0; 666 while (en.hasMoreElements()) { 667 arr[i] = "" + en.nextElement(); 668 i++; 669 } 670 java.util.Arrays.sort(arr); 671 return arr; 672 } 673 674 public Turnout getByEcosObject(int ecosObject) { 675 return _tecos.get(Integer.valueOf(ecosObject)); 676 } 677 678 public void refreshItems() { 679 /*ask to be notified about newly created turnouts on the layout. 680 Doing the request to view the list, will also kick off a request to 681 view on each individual turnout*/ 682 EcosMessage m = new EcosMessage("request(11, view)"); 683 tc.sendEcosMessage(m, this); 684 for (Integer ecosObjectId : _tecos.keySet()) { 685 EcosMessage em = new EcosMessage("release(" + ecosObjectId + ",view)"); 686 tc.sendEcosMessage(em, this); 687 em = new EcosMessage("get(" + ecosObjectId + ",state)"); 688 tc.sendEcosMessage(em, this); 689 em = new EcosMessage("request(" + ecosObjectId + ",view)"); 690 tc.sendEcosMessage(em, this); 691 } 692 } 693 694 @Override 695 @Nonnull 696 public String createSystemName(@Nonnull String curAddress, @Nonnull String prefix) throws JmriException { 697 int iName; 698 try { 699 iName = Integer.parseInt(curAddress); 700 } catch (NumberFormatException ex) { 701 throw new JmriException("Hardware Address passed "+curAddress+" should be a number."); 702 } 703 return prefix + typeLetter() + iName; 704 } 705 706 /** 707 * Validates to contain at least 1 number . . . 708 * <p> 709 * TODO: Custom validation for EcosTurnoutManager could be improved. 710 * {@inheritDoc} 711 */ 712 @Override 713 @Nonnull 714 public String validateSystemNameFormat(@Nonnull String name, @Nonnull java.util.Locale locale) throws jmri.NamedBean.BadSystemNameException { 715 return validateSystemNameFormatOnlyNumeric(name, locale); 716 } 717 718 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EcosTurnoutManager.class); 719 720}