001package jmri.jmrix.can.cbus; 002 003import java.util.EnumSet; 004import javax.annotation.CheckForNull; 005import javax.annotation.Nonnull; 006import jmri.jmrix.AbstractMessage; 007import jmri.jmrix.can.CanFrame; 008 009/** 010 * ENUM to represent various CBUS OPC Filters. 011 * 012 * @author Steve Young (C) 2020 013 */ 014public enum CbusFilterType { 015 CFIN(Bundle.getMessage("Incoming"),null) { 016 @Override 017 public int action(AbstractMessage m, CbusFilter cf) { 018 if (m instanceof jmri.jmrix.can.CanReply) { 019 return super.action(m,cf); 020 } 021 return -1; 022 } }, 023 CFOUT(Bundle.getMessage("Outgoing"),null) { 024 @Override 025 public int action(AbstractMessage m, CbusFilter cf) { 026 if (m instanceof jmri.jmrix.can.CanMessage) { 027 return super.action(m, cf); 028 } 029 return -1; 030 } }, 031 CFEVENT(Bundle.getMessage("CbusEvents"),null), 032 CFEVENTMIN(Bundle.getMessage("MinEvent"),CFEVENT) { 033 @Override 034 public int action(AbstractMessage m, CbusFilter cf) { 035 if ( CbusMessage.getEvent(m) < cf.getEvMin()) { 036 return super.action(m,cf); 037 } 038 return -1; 039 } 040 }, 041 CFEVENTMAX(Bundle.getMessage("MaxEvent"),CFEVENT) { 042 @Override 043 public int action(AbstractMessage m, CbusFilter cf) { 044 if ( CbusMessage.getEvent(m) > cf.getEvMax()){ 045 return super.action(m,cf); 046 } 047 return -1; 048 } }, 049 CFON(Bundle.getMessage("CbusOnEvents"),CFEVENT), 050 CFOF(Bundle.getMessage("CbusOffEvents"),CFEVENT), 051 CFSHORT(Bundle.getMessage("ShortEvents"),CFEVENT), 052 CFLONG(Bundle.getMessage("LongEvents"),CFEVENT), 053 CFSTD(Bundle.getMessage("StandardEvents"),CFEVENT), 054 CFREQUEST(Bundle.getMessage("RequestEvents"),CFEVENT), 055 CFRESPONSE(Bundle.getMessage("ResponseEvents"),CFEVENT), 056 CFED0(Bundle.getMessage("EVD0"),CFEVENT), 057 CFED1(Bundle.getMessage("EVD1"),CFEVENT), 058 CFED2(Bundle.getMessage("EVD2"),CFEVENT), 059 CFED3(Bundle.getMessage("EVD3"),CFEVENT), 060 061 CFDATA(Bundle.getMessage("OPC_DA"),null), 062 CFACDAT("ACDAT",CFDATA), 063 CFDDES("DDES + DDWS",CFDATA), 064 CFRQDAT("RQDAT",CFDATA), 065 CFARDAT("ARDAT",CFDATA), 066 CFDDRS("DDRS",CFDATA), 067 CFRQDDS("RQDDS",CFDATA), 068 CFCABDAT("CABDAT",CFDATA), 069 070 CFCS(Bundle.getMessage("CommandStation"),null), 071 CFCSAQRL(Bundle.getMessage("LocoCommands"),CFCS), 072 CFCSKA(Bundle.getMessage("KeepAlive"),CFCS), 073 CFCSDSPD(Bundle.getMessage("SpeedDirection"),CFCS), 074 CFCSFUNC(Bundle.getMessage("Functions"),CFCS), 075 CFCSPROG(Bundle.getMessage("Programming"),CFCS), 076 CFCSLC(Bundle.getMessage("LayoutCommands"),CFCS), 077 CFCSC(Bundle.getMessage("CommandStationControl"),CFCS), 078 079 CFNDCONFIG(Bundle.getMessage("NodeConfiguration"),null), 080 CFNDSETUP(Bundle.getMessage("GeneralNodeSetup"),CFNDCONFIG), 081 CFNDVAR(Bundle.getMessage("NodeVariables"),CFNDCONFIG), 082 CFNDEV(Bundle.getMessage("NodeEvents"),CFNDCONFIG), 083 CFNDNUM(Bundle.getMessage("NodeNumbers"),CFNDCONFIG), 084 085 CFMISC(Bundle.getMessage("Misc"),null), 086 CFEXTRTR("Extended / RTR",CFMISC){ 087 @Override 088 public int action(AbstractMessage m, CbusFilter cf) { 089 if (m instanceof CanFrame && ((CanFrame) m).extendedOrRtr() ) { 090 if ( cf.isFilterActive(ordinal()) ){ 091 return ordinal(); 092 } else { 093 return -2; // special return as unable to contiinue filtering if extended or rtr 094 } 095 } 096 return -1; 097 } }, 098 CFNETWK(Bundle.getMessage("NetworkCommands"),CFMISC), 099 CFCLOCK(Bundle.getMessage("CBUS_FCLK"),CFMISC), 100 CFOTHER(Bundle.getMessage("Others"),CFMISC), 101 CFUNKNOWN(Bundle.getMessage("Unknown"),CFMISC), 102 103 CFNODE(Bundle.getMessage("CbusNodes"),null) { 104 @Override 105 public String getToolTip(){ 106 return null; 107 } 108 109 }, 110 CFNODEMIN(Bundle.getMessage("MinNode"),CFNODE) { 111 @Override 112 public int action(AbstractMessage m, CbusFilter cf) { 113 if ( CbusMessage.getNodeNumber(m) < cf.getNdMin()){ 114 return super.action(m, cf); 115 } 116 return -1; 117 } 118 }, 119 CFNODEMAX(Bundle.getMessage("MaxNode"),CFNODE) { 120 @Override 121 public int action(AbstractMessage m, CbusFilter cf) { 122 if ( CbusMessage.getNodeNumber(m) > cf.getNdMax()){ 123 return super.action(m, cf); 124 } 125 return -1; 126 } }; 127 128 /** 129 * Perform Filter check for a particular message. 130 * Can be overridden by specific filters. 131 * 132 * @param m CanMessage or CanReply 133 * @param cf main CbusFilter instance 134 * @return Filter category which blocked, else -1 or -2 if passed 135 */ 136 public int action(AbstractMessage m, @Nonnull CbusFilter cf){ 137 if ( cf.isFilterActive(ordinal()) ){ 138 return ordinal(); 139 } else { 140 return -1; 141 } 142 } 143 144 private final String _bundleString; 145 private final CbusFilterType _category; 146 147 /** 148 * Create new CbusFilterType. 149 */ 150 CbusFilterType(String bundle, CbusFilterType category) { 151 this._bundleString=bundle; 152 this._category = category; 153 } 154 155 /** 156 * Get Filter Name 157 * @return Filter Name 158 */ 159 public final String getName(){ 160 return _bundleString; 161 } 162 163 /** 164 * Get Filter Category 165 * @return Filter Category, else null if Category Head 166 */ 167 @CheckForNull 168 public final CbusFilterType getCategory() { 169 return _category; 170 } 171 172 /** 173 * Get an EnumSet of Category Heads 174 * @return set 175 */ 176 public static final java.util.Set<CbusFilterType> getCatHeads() { 177 EnumSet<CbusFilterType> catSet = EnumSet.noneOf(CbusFilterType.class); 178 catSet.add(CFEVENT); 179 catSet.add(CFNODE); 180 catSet.add(CFDATA); 181 catSet.add(CFCS); 182 catSet.add(CFNDCONFIG); 183 catSet.add(CFMISC); 184 return catSet; 185 } 186 187 /** 188 * Is the Filter a parent of a category? 189 * @return true if category parent 190 */ 191 public final boolean isCategoryHead() { 192 return getCatHeads().contains(this); 193 } 194 195 /** 196 * Should the Filter always be displayed? 197 * @return true if category head or in / out filter. 198 */ 199 public final boolean alwaysDisplay() { 200 java.util.Set<CbusFilterType> alwaysDisplay = getCatHeads(); 201 alwaysDisplay.add(CFIN); 202 alwaysDisplay.add(CFOUT); 203 return alwaysDisplay.contains(this); 204 } 205 206 /** 207 * Get if the Filter needs to display a number spinner 208 * @return true to display a spinner 209 */ 210 public final boolean showSpinners() { 211 EnumSet<CbusFilterType> spinnerSet = EnumSet.noneOf(CbusFilterType.class); 212 spinnerSet.addAll(EnumSet.of(CFEVENTMIN,CFEVENTMAX,CFNODEMIN,CFNODEMAX)); 213 return spinnerSet.contains(this); 214 } 215 216 /** 217 * Get All Filters for a particular OPC 218 * @param opc OPC to get Filter List for 219 * @return set of Filters to use for the OPC. 220 */ 221 @Nonnull 222 public static final EnumSet<CbusFilterType> allFilters(int opc) { 223 EnumSet<CbusFilterType> mergedSet = EnumSet.noneOf(CbusFilterType.class); 224 mergedSet.addAll(EnumSet.of(CFIN,CFOUT,CFEXTRTR)); 225 mergedSet.addAll(CbusOpCodes.getOpcFilters(opc)); 226 if (mergedSet.contains(CbusFilterType.CFEVENT)){ 227 mergedSet.addAll(EnumSet.of(CbusFilterType.CFEVENTMIN,CbusFilterType.CFEVENTMAX)); 228 } 229 if (mergedSet.contains(CbusFilterType.CFNODE)){ 230 mergedSet.addAll(EnumSet.of(CbusFilterType.CFNODEMIN,CbusFilterType.CFNODEMAX)); 231 } 232 return mergedSet; 233 } 234 235 /** 236 * Get ToolTip Text for the Filter 237 * @return HMTL list of OPCs with description, may be null if no ToolTip 238 */ 239 @CheckForNull 240 public String getToolTip(){ 241 StringBuilder t = new StringBuilder(); 242 for ( int i=0 ; (i < 257) ; i++) { 243 if (CbusOpCodes.getOpcFilters(i).contains(this) 244 && !CbusOpCodes.getOpcName(i).isEmpty()){ 245 t.append(CbusOpCodes.getOpcName(i)) 246 .append(" : ") 247 .append(Bundle.getMessage("CBUS_" + CbusOpCodes.getOpcName(i))) 248 .append(" : ") 249 .append(Bundle.getMessage("CTIP_" + CbusOpCodes.getOpcName(i))) 250 .append("<br>"); 251 } 252 } 253 if (!t.toString().isEmpty()){ 254 t.insert(0,"<html>"); 255 t.append("</html>"); 256 return t.toString(); 257 } 258 return null; 259 } 260 261 /** 262 * Get Filter Type by name. 263 * @param name the #getName string to search for. 264 * @return Filter Type, or null if not found. 265 */ 266 @CheckForNull 267 public static CbusFilterType getFilterByName(String name) { 268 for ( CbusFilterType type : CbusFilterType.values() ) { 269 if ( type.getName().equals(name) ) { 270 return type; 271 } 272 } 273 return null; 274 } 275 276}