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