001package jmri.jmrit.ctc; 002 003import java.beans.PropertyChangeListener; 004import java.util.ArrayList; 005 006import jmri.InstanceManager; 007import jmri.NamedBeanHandle; 008import jmri.NamedBeanHandleManager; 009import jmri.Turnout; 010import jmri.TurnoutManager; 011import jmri.jmrit.ctc.ctcserialdata.ProjectsCommonSubs; 012 013/** 014 * This object additionally supports "inverted feedback", so that when someone 015 * calls "getKnownState", (typically my own code in this CTC project) we return 016 * the "adjusted" value based upon "inverted feedback". 017 * @author Gregory J. Bedlek Copyright (C) 2018, 2019, 2020 018 * Prefix NBH = Named Bean Handler.... 019 */ 020 021public class NBHTurnout { 022 023// Special case sane return values: 024 public static final int DEFAULT_TURNOUT_STATE_RV = Turnout.CLOSED; // A valid state, just "B.S.". 025// Standard sane return values for the types indicated: 026// public static final Object DEFAULT_OBJECT_RV = null; // For any function that returns something derived from Java's Object. 027// public static final boolean DEFAULT_BOOLEAN_RV = false; // For any function that returns boolean. 028 public static final int DEFAULT_INT_RV = 0; // For any function that returns int. 029// public static final long DEFAULT_LONG_RV = 0; // For any function that returns long. 030// public static final float DEFAULT_FLOAT_RV = (float)0.0; // For any function that returns float. 031// public static final String DEFAULT_STRING_RV = "UNKNOWN"; // NOI18N For any function that returns String. 032 033// The "thing" we're protecting: 034 private NamedBeanHandle<Turnout> _mNamedBeanHandleTurnout; 035 private final String _mUserIdentifier; 036 private final String _mParameter; 037 private final boolean _mFeedbackDifferent; 038 private final ArrayList<PropertyChangeListener> _mArrayListOfPropertyChangeListeners = new ArrayList<>(); 039 040 public NBHTurnout(String module, String userIdentifier, String parameter, String turnout, boolean FeedbackDifferent) { 041 _mUserIdentifier = userIdentifier; 042 _mParameter = parameter; 043 _mFeedbackDifferent = FeedbackDifferent; 044 Turnout tempTurnout = getSafeExistingJMRITurnout(module, _mUserIdentifier, _mParameter, turnout); 045 if (tempTurnout != null) { 046 _mNamedBeanHandleTurnout = InstanceManager.getDefault(NamedBeanHandleManager.class).getNamedBeanHandle(turnout, tempTurnout); 047 } else { 048 _mNamedBeanHandleTurnout = null; 049 } 050 if (valid()) InstanceManager.getDefault(CtcManager.class).putNBHTurnout(turnout, this); 051 } 052 053// Special constructor to create a NBHTurnout with a null NamedBeanHandle. Used to initialize turnout fields. 054 public NBHTurnout(String module, String userIdentifier, String parameter) { 055 _mUserIdentifier = userIdentifier; 056 _mParameter = parameter; 057 _mFeedbackDifferent = false; 058 _mNamedBeanHandleTurnout = null; 059 if (valid()) InstanceManager.getDefault(CtcManager.class).putNBHTurnout("dummy", this); 060 } 061 062 public boolean valid() { return _mNamedBeanHandleTurnout != null; } // For those that want to know the internal state. 063 064 public Turnout getBean() { 065 if (valid()) return _mNamedBeanHandleTurnout.getBean(); 066 return null; 067 } 068 069 public NamedBeanHandle<?> getBeanHandle() { 070 if (valid()) return _mNamedBeanHandleTurnout; 071 return null; 072 } 073 074 075 private static Turnout getSafeExistingJMRITurnout(String module, String userIdentifier, String parameter, String turnout) { 076 try { return getExistingJMRITurnout(module, userIdentifier, parameter, turnout); } catch (CTCException e) { e.logError(); } 077 return null; 078 } 079// turnout is NOT optional and cannot be null. Raises Exception in ALL error cases. 080 static private Turnout getExistingJMRITurnout(String module, String userIdentifier, String parameter, String turnout) throws CTCException { 081 if (!ProjectsCommonSubs.isNullOrEmptyString(turnout)) { 082 // Cannot use a constant Instance manager reference due to the dynamic nature of tests. 083 Turnout returnValue = InstanceManager.getDefault(TurnoutManager.class).getTurnout(turnout); 084 if (returnValue == null) { throw new CTCException(module, userIdentifier, parameter, Bundle.getMessage("NBHTurnoutDoesNotExist") + " " + turnout); } // NOI18N 085 return returnValue; 086 } else { throw new CTCException(module, userIdentifier, parameter, Bundle.getMessage("RequiredTurnoutMissing")); } // NOI18N 087 } 088 089 public int getKnownState() { 090 if (_mNamedBeanHandleTurnout == null) return DEFAULT_TURNOUT_STATE_RV; 091 int knownState = _mNamedBeanHandleTurnout.getBean().getKnownState(); 092 if (!_mFeedbackDifferent) { // Normal: 093 return knownState; 094 } else { // Reversed: 095 return knownState == Turnout.CLOSED ? Turnout.THROWN : Turnout.CLOSED; 096 } 097 } 098 099 public void setCommandedState(int s) { 100 if (_mNamedBeanHandleTurnout == null) return; 101 _mNamedBeanHandleTurnout.getBean().setCommandedState(s); 102 } 103 104 public int getFeedbackMode() { 105 if (_mNamedBeanHandleTurnout == null) return DEFAULT_INT_RV; 106 return _mNamedBeanHandleTurnout.getBean().getFeedbackMode(); 107 } 108 109 public void addPropertyChangeListener(PropertyChangeListener propertyChangeListener) { 110 if (_mNamedBeanHandleTurnout == null) return; 111 _mNamedBeanHandleTurnout.getBean().addPropertyChangeListener(propertyChangeListener); 112 _mArrayListOfPropertyChangeListeners.add(propertyChangeListener); 113 } 114 115 public void removePropertyChangeListener(PropertyChangeListener propertyChangeListener) { 116 if (_mNamedBeanHandleTurnout == null) return; 117 _mNamedBeanHandleTurnout.getBean().removePropertyChangeListener(propertyChangeListener); 118 _mArrayListOfPropertyChangeListeners.remove(propertyChangeListener); 119 } 120 121 /** 122 * @return The turnout's handle name. 123 */ 124 public String getHandleName() { 125 return valid() ? _mNamedBeanHandleTurnout.getName() : ""; 126 } 127 128 /** 129 * For Unit testing only. 130 * @return Returns the present number of property change listeners registered with us so far. 131 */ 132 public int testingGetCountOfPropertyChangeListenersRegistered() { 133 return _mArrayListOfPropertyChangeListeners.size(); 134 } 135 136}