package tmcsim.paramicscommunicator; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Observable; import java.util.Timer; import java.util.TimerTask; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import tmcsim.common.CADProtocol.PARAMICS_ACTIONS; import tmcsim.common.CADProtocol.PARAMICS_COMM_TAGS; import tmcsim.paramicscommunicator.FileIOUpdate.IO_TYPE; /** * The ParamicsFileReader handles reading fom a target file which is written to * by Paramics. Once initialized, a timer task is started which periodically * checks the target file for updates. If the file has been modified, it is read * and cleared. The read data is transmitted to the CAD Simulator. * * @author Matthew Cechini * @version 0.1 Notes by jdalbey: Paramics modeler is licensed third-party * software and apparently we don't have an SDK for it. So it seems the * workaround was to communicate with it via data files that the modeler * produces. Wacky, but it works for now. Look at the run() method below: if * (lastModified < inputFile.lastModified()) Means it's watching the file to * see if it has been updated by the modeler. */ public class ParamicsFileReader extends Observable { /** * Error Logger. */ private Logger paramLogger = Logger.getLogger("tmcsim.paramicscommunicator"); /** * FileReader ID used for creation of the ParamicsCommMessage */ private String readerID = null; /** * File reference to the file where data is read. */ private File inputFile = null; /** * FileReader used to read data from the input file. */ private FileReader fileReader = null; /** * FileWriter used to clear the input file. */ private FileWriter fileWriter = null; /** * Value (seconds since 1/1/1970) of input file's last modification time. */ private long lastModified = 0; /** * Timer used to schedule file reading tasks. */ private Timer readerTimer = null; /** * Duration (in seconds) that the TimerTask will be scheduled to read from * the target file. */ private long readerInterval; /** * Time formatter for diagnostic messages */ private SimpleDateFormat formatter; /** * A TimerTask to read from the target file. If the file has been modified * since last read, read the file and transmit the data to the CAD * Simulator. * * @author Matthew Cechini */ private class ReaderTimerTask extends TimerTask { public void run() { // System.out.println( // "Checking last modified time on " + inputFile.getName() // + formatter.format(lastModified) + ":" + formatter.format(inputFile.lastModified())); if (lastModified < inputFile.lastModified()) { try { Document readerDoc = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); Element readerElem = readerDoc.createElement(PARAMICS_COMM_TAGS.READER.tag); readerElem.setAttribute(PARAMICS_COMM_TAGS.ID.tag, readerID); readerElem.setAttribute(PARAMICS_COMM_TAGS.ACTION.tag, PARAMICS_ACTIONS.READ_FILE.action); Element messageElem = readerDoc.createElement(PARAMICS_COMM_TAGS.MESSAGE.tag); String fileContents = readFromFile(); messageElem.appendChild(readerDoc.createTextNode(fileContents)); readerElem.appendChild(messageElem); readerDoc.appendChild(readerElem); setChanged(); notifyObservers(readerDoc); } catch (Exception e) { paramLogger.logp(Level.SEVERE, "ParamicsFileReader.ReaderTimerTask", "run()", "Exception in reading from file: " + inputFile.getName(), e); } } } } /** * Constructor. Set the reader id and interval from the parsed * ParamicsCommMessage. The interval is found within the first three * characters of the object's "message" data member. Create a file object * for the target file, and create a new file if it does not already exist. * Instantiate the timer and ReaderTimerTask to begin periodic reading of * the file. * * @param workingDir Target working directory. // Oops, the following seem * obsolete * @param mess ParamicsCommMessage object containing registration data. * @param theComm Reference to the ParamicsCommunicator. */ public ParamicsFileReader(String workingDir, String id, Integer interval, String targetFile) { try { formatter = new SimpleDateFormat("HH:mm:ss"); readerID = id; readerInterval = interval; inputFile = new File(workingDir + targetFile); if (!inputFile.exists()) { inputFile.createNewFile(); } readerTimer = new Timer(); readerTimer.scheduleAtFixedRate(new ReaderTimerTask(), 0L, readerInterval * 1000); } catch (IOException ioe) { paramLogger.logp(Level.SEVERE, "ParamicsFileReader", "Constructor()", "Exception in initializing file reading of "+workingDir + targetFile, ioe); } } /** * Method opens the target file and reads all contents. The file is then * cleared. * * @returns * @throws IOException if there is an error in reading or writing to the * file. */ private String readFromFile() throws IOException { char[] input = new char[(int) inputFile.length()]; fileReader = new FileReader(inputFile); fileReader.read(input); fileReader.close(); //make sure the new file has a modified time that is different try { Thread.sleep(1000); } catch (Exception e) { } //clear file after reading contents fileWriter = new FileWriter(inputFile); fileWriter.write(""); fileWriter.close(); lastModified = inputFile.lastModified(); // System.out.println( // "Read from a file last modified at " + formatter.format(lastModified)); setChanged(); notifyObservers(new FileIOUpdate(IO_TYPE.READ, readerID, (long) input.length)); return new String(input); } }