001package jmri.jmrix.can.cbus.node; 002 003import java.util.ArrayList; 004import java.util.Date; 005import java.util.Objects; 006import jmri.jmrix.can.CanMessage; 007import jmri.jmrix.can.CanReply; 008import jmri.jmrix.can.CanSystemConnectionMemo; 009import jmri.jmrix.can.cbus.node.CbusNodeConstants.BackupType; 010 011/** 012 * Class to represent a node imported from FCU file or CbusNodeXml. 013 * 014 * @author Steve Young Copyright (C) 2019 015 */ 016public class CbusNodeFromBackup extends CbusNode implements Comparable<CbusNodeFromBackup> { 017 018 private Date _timeStamp; 019 private String _backupComment; 020 private BackupType _backupType; 021 022 /** 023 * Create a new CbusNodeFrommBackup by connection type and Node Number 024 * 025 * @param connmemo CAN Connection 026 * @param nodenumber Node Number between 1 and 65535 027 */ 028 public CbusNodeFromBackup ( CanSystemConnectionMemo connmemo, int nodenumber ){ 029 super( connmemo, nodenumber ); 030 _backupComment = ""; 031 } 032 033 /** 034 * Create a new CbusNodeFrommBackup from an existing Node 035 * 036 * @param node The Node to make a copy of 037 * @param timeStamp to set the Backup TimeStamp 038 */ 039 public CbusNodeFromBackup ( CbusNode node, Date timeStamp) { 040 super( null, node.getNodeNumber() ); 041 _backupComment = ""; 042 setBackupResult(BackupType.INCOMPLETE); 043 _timeStamp = timeStamp; 044 if (node.getNodeParamManager().getParameters()!=null) { 045 super.getNodeParamManager().setParameters(node.getNodeParamManager().getParameters()); 046 } else { 047 setBackupResult(BackupType.COMPLETEDWITHERROR); 048 } 049 if (node.getNodeNvManager().getNvArray()!=null) { 050 super.getNodeNvManager().setNVs(node.getNodeNvManager().getNvArray()); 051 } else { 052 setBackupResult(BackupType.COMPLETEDWITHERROR); 053 } 054 // copy events 055 ArrayList<CbusNodeEvent> _tmpArr = node.getNodeEventManager().getEventArray(); 056 if (_tmpArr !=null) { 057 _tmpArr.forEach((ndEv) -> { 058 getNodeEventManager().addNewEvent(new CbusNodeEvent( ndEv )); 059 }); 060 } else { 061 setBackupResult(BackupType.COMPLETEDWITHERROR); 062 } 063 if (getBackupResult() == BackupType.INCOMPLETE) { 064 setBackupResult(BackupType.COMPLETE); 065 } 066 } 067 068 /** 069 * Ignores incoming and outgoing CAN Frames 070 * {@inheritDoc} 071 */ 072 @Override 073 public CbusNodeCanListener getNewCanListener(){ 074 return new DoNothingCanListener(); 075 } 076 077 /** 078 * Set the Backup DateTime 079 * @param thisDate Timestamp 080 */ 081 protected void setBackupTimeStamp( Date thisDate){ 082 _timeStamp = thisDate; 083 } 084 085 /** 086 * Get the Backup DateTime 087 * @return DateTime in format 088 */ 089 public Date getBackupTimeStamp(){ 090 return _timeStamp; 091 } 092 093 /** 094 * Set the Backup Result 095 * @param type Backup Type Enum 096 */ 097 protected final void setBackupResult(BackupType type) { 098 _backupType = type; 099 } 100 101 /** 102 * Get the Backup Result 103 * @return enum 104 */ 105 public final BackupType getBackupResult() { 106 return _backupType; 107 } 108 109 /** 110 * Set the backup comment 111 * @param backupComment text representation of the single backup state 112 */ 113 public void setBackupComment(String backupComment) { 114 _backupComment = backupComment; 115 } 116 117 /** 118 * Get the Backup Comment 119 * eg. Completed No Issues, 9 NVs, 12 Events with 4 EVs 120 * 121 * @return index number, -1 if unset 122 */ 123 public String getBackupComment() { 124 return _backupComment; 125 } 126 127 /** 128 * Add an event to the Node in backup format 129 * 130 * @param nn Event Node Number 131 * @param en Event Event Number 132 * @param evVars Event Variable Hex String eg. "0102DC3AFF" 133 */ 134 public void addBupEvent(int nn, int en, String evVars){ 135 CbusNodeEvent buildEv = new CbusNodeEvent( nn, en , getNodeNumber(), evVars); 136 getNodeEventManager().addNewEvent(buildEv); 137 } 138 139 /** 140 * Get a String comparison with another CbusNodeFromBackup 141 * 142 * @param toTest The CbusNodeFromBackup to test against 143 * @return eg. "Parameters Changed" 144 */ 145 public String compareWithString( CbusNodeFromBackup toTest) { 146 147 if (toTest==null){ 148 return (""); 149 } 150 151 if (equals(toTest)) { 152 return Bundle.getMessage("NoChanges"); 153 } 154 155 StringBuilder text = new StringBuilder(); 156 157 if (!(getNodeParamManager().getParameterHexString().equals(toTest.getNodeParamManager().getParameterHexString()))){ 158 text.append("Parameters Changed"+" "); 159 } 160 161 if (!(getNodeNvManager().getNvHexString().equals(toTest.getNodeNvManager().getNvHexString()))){ 162 text.append("NV's Changed"+" "); 163 } 164 165 if ( getNodeEventManager().getTotalNodeEvents() != toTest.getNodeEventManager().getTotalNodeEvents() ) { 166 text.append("Number Events Changed"+" "); 167 } else if (getEventArrayHash()!=toTest.getEventArrayHash()){ 168 text.append("Events Changed"+" "); 169 } 170 171 if (text.toString().isEmpty()) { 172 text.append(Bundle.getMessage("NoChanges")); 173 } 174 175 return text.toString(); 176 177 } 178 179 /** 180 * {@inheritDoc} 181 * Compares to the Time Date Stamp of the Backup 182 */ 183 @Override 184 public int compareTo(CbusNodeFromBackup o) { 185 return this.getBackupTimeStamp().compareTo(o.getBackupTimeStamp()); 186 } 187 188 /** 189 * {@inheritDoc} 190 * <p> 191 * Used for highlighting changes to Node Backups, 192 * so the Date Time Stamp does NOT need to be equal. 193 * checking for Node Number, Parameters, NVs, Events. 194 * Events can be in any order, are sorted mid comparison. 195 */ 196 @Override 197 public boolean equals(Object obj) { 198 if (obj == this) { 199 return true; 200 } 201 if (!(obj instanceof CbusNodeFromBackup)) { 202 return false; 203 } 204 CbusNodeFromBackup t = (CbusNodeFromBackup) obj; 205 if (this.getNodeNumber() != t.getNodeNumber()) { 206 return false; 207 } 208 if (!(this.getNodeParamManager().getParameterHexString().equals(t.getNodeParamManager().getParameterHexString()))){ 209 return false; 210 } 211 if (!(this.getNodeNvManager().getNvHexString().equals(t.getNodeNvManager().getNvHexString()))){ 212 return false; 213 } 214 if ( this.getNodeEventManager().getTotalNodeEvents() != t.getNodeEventManager().getTotalNodeEvents() ) { 215 return false; 216 } 217 218 ArrayList<CbusNodeEvent> thisEvs = this.getNodeEventManager().getEventArray(); 219 ArrayList<CbusNodeEvent> otherEvs = t.getNodeEventManager().getEventArray(); 220 221 if ( thisEvs !=null && otherEvs !=null) { 222 java.util.Collections.sort(thisEvs); 223 java.util.Collections.sort(otherEvs); 224 } 225 return this.getEventArrayHash() == t.getEventArrayHash(); 226 } 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override public int hashCode() { 232 return Objects.hash(getNodeNumber(),getNodeParamManager().getParameterHexString(), 233 getNodeNvManager().getNvHexString(),getEventArrayHash()); 234 } 235 236 /** 237 * Get a Hashcode for the Event Array 238 * @return 0 if event array null 239 */ 240 public int getEventArrayHash(){ 241 ArrayList<CbusNodeEvent> _tmpArr = getNodeEventManager().getEventArray(); 242 if ( _tmpArr == null ) { 243 return 0; 244 } else { 245 return _tmpArr.hashCode(); 246 } 247 } 248 249 /** 250 * toString reports the Node Number Name and backup timestamp 251 * @return string eg "1234 UserName Backup Sun Jul 07 22:41:22". 252 * {@inheritDoc} 253 */ 254 @Override 255 public String toString(){ 256 return super.toString()+ " Backup " + getBackupTimeStamp(); 257 } 258 259 /** 260 * Ignores Incoming and Outgoing CAN Frames. 261 */ 262 protected static class DoNothingCanListener extends CbusNodeCanListener { 263 264 public DoNothingCanListener(){ 265 super(null,null); 266 } 267 268 /** 269 * Ignores outgoing CAN Frames. 270 * {@inheritDoc} 271 */ 272 @Override 273 public void message(CanMessage m) {} 274 275 /** 276 * Ignores incoming CAN Frames. 277 * {@inheritDoc} 278 */ 279 @Override 280 public void reply(CanReply m) {} 281 282} 283 284 // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusNodeFromBackup.class); 285 286}