001package jmri.implementation; 002 003import com.fasterxml.jackson.databind.util.StdDateFormat; 004 005import java.text.*; 006import java.util.Calendar; 007import java.util.Date; 008import java.util.Objects; 009 010import javax.annotation.CheckForNull; 011 012import jmri.*; 013 014import org.jdom2.Element; 015import org.slf4j.Logger; 016import org.slf4j.LoggerFactory; 017 018/** 019 * Concrete implementation of the {@link jmri.IdTag} interface for the Internal 020 * system. 021 * <hr> 022 * This file is part of JMRI. 023 * <p> 024 * JMRI is free software; you can redistribute it and/or modify it under the 025 * terms of version 2 of the GNU General Public License as published by the Free 026 * Software Foundation. See the "COPYING" file for a copy of this license. 027 * <p> 028 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 029 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 030 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 031 * 032 * @author Matthew Harris Copyright (C) 2011 033 * @since 2.11.4 034 */ 035public class DefaultIdTag extends AbstractIdTag { 036 037 private int currentState = UNKNOWN; 038 039 public DefaultIdTag(String systemName) { 040 super(systemName); 041 setWhereLastSeen(null); 042 } 043 044 public DefaultIdTag(String systemName, String userName) { 045 super(systemName, userName); 046 setWhereLastSeen(null); 047 } 048 049 public final static String PROPERTY_WHEN_LAST_SEEN = "whenLastSeen"; 050 public final static String PROPERTY_WHERE_LAST_SEEN = "whereLastSeen"; 051 052 @Override 053 public int compareTo(NamedBean n2) { 054 Objects.requireNonNull(n2); 055 String o1 = this.getSystemName(); 056 String o2 = n2.getSystemName(); 057 int p1len = Manager.getSystemPrefixLength(o1); 058 int p2len = Manager.getSystemPrefixLength(o2); 059 int comp = o1.substring(0, p1len).compareTo(o2.substring(0, p2len)); 060 if (comp != 0) 061 return comp; 062 comp = o1.compareTo(o2); 063 return comp; 064 } 065 066 @Override 067 public final void setWhereLastSeen(@CheckForNull Reporter r) { 068 Reporter oldWhere = this.whereLastSeen; 069 Date oldWhen = this.whenLastSeen; 070 this.whereLastSeen = r; 071 if (r != null) { 072 this.whenLastSeen = getDateNow(); 073 } else { 074 this.whenLastSeen = null; 075 } 076 setCurrentState(r != null ? SEEN : UNSEEN); 077 firePropertyChange(PROPERTY_WHERE_LAST_SEEN, oldWhere, this.whereLastSeen); 078 firePropertyChange(PROPERTY_WHEN_LAST_SEEN, oldWhen, this.whenLastSeen); 079 } 080 081 private Date getDateNow() { 082 return InstanceManager.getDefault(IdTagManager.class).isFastClockUsed() 083 ? InstanceManager.getDefault(ClockControl.class).getTime() 084 : Calendar.getInstance().getTime(); 085 } 086 087 private void setCurrentState(int state) { 088 try { 089 setState(state); 090 } catch (JmriException ex) { 091 log.warn("Problem setting state of IdTag {} {}", getSystemName(),ex.getMessage()); 092 } 093 } 094 095 @Override 096 public void setState(int s) throws JmriException { 097 this.currentState = s; 098 } 099 100 @Override 101 public int getState() { 102 return this.currentState; 103 } 104 105 @Override 106 public Element store(boolean storeState) { 107 Element e = new Element("idtag"); // NOI18N 108 e.addContent(new Element("systemName").addContent(this.mSystemName)); // NOI18N 109 String uName = this.getUserName(); 110 if (uName != null && !uName.isEmpty()) { 111 e.addContent(new Element("userName").addContent(uName)); // NOI18N 112 } 113 String comment = this.getComment(); 114 if ((comment != null) && (!comment.isEmpty())) { 115 e.addContent(new Element("comment").addContent(comment)); // NOI18N 116 } 117 Reporter whereLast = this.getWhereLastSeen(); 118 if (whereLast != null && storeState) { 119 e.addContent(new Element(PROPERTY_WHERE_LAST_SEEN).addContent(whereLast.getSystemName())); 120 } 121 if (this.getWhenLastSeen() != null && storeState) { 122 e.addContent(new Element(PROPERTY_WHEN_LAST_SEEN).addContent(new StdDateFormat().format(this.getWhenLastSeen()))); 123 } 124 return e; 125 } 126 127 /** 128 * Load an idtag xml element. 129 * whenLastSeen formats accepted JMRI 5.3.6 include 130 * yyyy-MM-dd'T'HH:mm:ss.SSSX 131 * yyyy-MM-dd'T'HH:mm:ss.SSS 132 * EEE, dd MMM yyyy HH:mm:ss zzz 133 * 134 * @param e element to load. 135 */ 136 @Override 137 public void load(Element e) { 138 if (e.getName().equals("idtag")) { // NOI18N 139 log.debug("Load IdTag element for {}", this.getSystemName()); 140 if (e.getChild("userName") != null) { // NOI18N 141 this.setUserName(e.getChild("userName").getText()); // NOI18N 142 } 143 if (e.getChild("comment") != null) { // NOI18N 144 this.setComment(e.getChild("comment").getText()); // NOI18N 145 } 146 if (e.getChild(PROPERTY_WHERE_LAST_SEEN) != null) { 147 try { 148 Reporter r = InstanceManager.getDefault(ReporterManager.class) 149 .provideReporter(e.getChild(PROPERTY_WHERE_LAST_SEEN).getText()); 150 this.setWhereLastSeen(r); 151 this.whenLastSeen = null; 152 } catch (IllegalArgumentException ex) { 153 log.warn("Failed to provide Reporter \"{}\" in load of \"{}\"", e.getChild(PROPERTY_WHERE_LAST_SEEN).getText(), getDisplayName()); 154 } 155 } 156 if (e.getChild(PROPERTY_WHEN_LAST_SEEN) != null) { 157 String lastSeenText = e.getChildText(PROPERTY_WHEN_LAST_SEEN); 158 log.debug("Loading {} When Last Seen: {}", getDisplayName(), lastSeenText); 159 try { // parse using ISO 8601 date format 160 this.whenLastSeen = new StdDateFormat().parse(lastSeenText); 161 } catch (ParseException ex) { 162 log.debug("ParseException in whenLastSeen ISO attempt: \"{}\"", lastSeenText, ex); 163 // next, try parse using how it was saved by JMRI < 5.3.5 164 try { 165 this.whenLastSeen = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).parse(lastSeenText); 166 } catch (ParseException ex2) { 167 log.warn("During load of IdTag \"{}\" {}", getDisplayName(), ex.getMessage()); 168 } 169 } 170 } 171 } else { 172 log.error("Not an IdTag element: \"{}\" for Tag \"{}\"", e.getName(), this.getDisplayName()); 173 } 174 } 175 176 private static final Logger log = LoggerFactory.getLogger(DefaultIdTag.class); 177 178}