package com.isti.xmax; import java.awt.Dimension; import java.awt.Frame; import java.awt.Point; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.StringTokenizer; import org.apache.log4j.Logger; import org.apache.commons.configuration.AbstractConfiguration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.SubnodeConfiguration; import org.apache.commons.configuration.XMLConfiguration; import com.isti.traceview.TraceViewException; import com.isti.traceview.common.Configuration; import com.isti.traceview.common.TimeInterval; import com.isti.traceview.gui.ColorModeBySegment; import com.isti.xmax.XMAXException; /** * <p> * This class holds configuration data. It reads configuration file and uses default values for * missed parameters. * </p> * <p> * It overwrites configuration parameters with command-line parameters. * </p> * <p> * Realize singleton pattern, i.e we can have only one configuration in the program. * </p> * * @author Max Kokoulin */ public class XMAXconfiguration extends Configuration { private static final Logger logger = Logger.getLogger(XMAXconfiguration.class); private Map<String, String> userDirectories = null; /** * Full pathname for quality control data file */ private String qCdataFileName = ""; /** * Location of xml picks database */ private String pickPath = ""; /** * Wildcarded mask for earthquakes definition files */ private String earthquakeFileMask; private String outputPath; /** * Time interval to load channels, correspond -b and -e command line options. */ private TimeInterval ti; private boolean showStatusBar = true; private boolean showCommandButtons = true; private boolean showCommandButtonsTop = false; private int frameState = Frame.MAXIMIZED_BOTH; private int[] framePos = new int[2]; private int[] frameSize = new int[2]; private String logFile = null; private static XMAXconfiguration instance = null; private XMLConfiguration config = null; private XMAXconfiguration() throws ConfigurationException, TraceViewException, XMAXException { setDefaultHTMLPattern("<html><head><title>XMAX report</title></head><body><h1>XMAX report</h1> </body></html>"); config = new XMLConfiguration(confFileName); userDirectories = new HashMap<String, String>(); ti = null; try { setUseTempData(false); setLogFile(config.getString("Configuration.LogFile", "XMAX.log")); setPanelCountUnit(PanelCountUnit.values()[config.getInt("Configuration.PanelCountUnit", 0)]); setUnitsInFrame(config.getInt("Configuration.UnitsInFrame", 1)); setMergeLocations(config.getBoolean("Configuration.MergeLocations", false)); setPanelOrder(ChannelSortType.values()[config.getInt("Configuration.PanelOrder", 0)]); setDataPath(config.getString("Configuration.Data.DataMask", "!")); setDataTempPath(config.getString("Configuration.Data.TempPath")); setQCdataFileName(config.getString("Configuration.Data.QCdataFile", "qc.xml")); setPickPath(config.getString("Configuration.Data.PickPath", "./Picks")); setStationInfoFileName(config.getString("Configuration.Data.StationInfoFile")); setEarthquakeFileMask(config.getString("Configuration.Data.EventFileMask")); setResponsePath(config.getString("Configuration.Data.ResponsePath", "/Responses")); // setAllowMultiplexedData(config.getBoolean("Configuration.Data.AllowMultiplexedData")); setOutputPath(config.getString("Configuration.OutputPath")); String startTimeStr = config.getString("Configuration.StartTime"); if (startTimeStr != null) { setStartTime(TimeInterval.parseDate(startTimeStr, TimeInterval.DateFormatType.DATE_FORMAT_MIDDLE)); } String endTimeStr = config.getString("Configuration.EndTime"); if (endTimeStr != null) { setEndTime(TimeInterval.parseDate(endTimeStr, TimeInterval.DateFormatType.DATE_FORMAT_MIDDLE)); } setScaleMode(config.getString("Configuration.View.ScaleMode", "AUTO")); setColorModeState(config.getString("Configuration.View.ColorMode", "SEGMENT"), false); setShowBigCursor(config.getBoolean("Configuration.View.ShowBigCursor", false)); setShowStatusBar(config.getBoolean("Configuration.View.ShowStatusBar", true)); setShowCommandButtons(config.getBoolean("Configuration.View.ShowCommandButtons", true)); setShowCommandButtonsTop(config.getBoolean("Configuration.View.ShowCommandButtonsTop", false)); @SuppressWarnings("unchecked") Iterator<String> it = config.getKeys("SessionData.UserDir"); while (it.hasNext()) { String key = it.next(); StringTokenizer st = new StringTokenizer(key, "."); if (st.countTokens() == 3) { userDirectories.put(key.substring(key.lastIndexOf('.') + 1), config.getString(key)); } } String state = config.getString("SessionData.Frame.State", "MAXIMIZED_BOTH"); if (state.equals("NORMAL")) { frameState = Frame.NORMAL; } else if (state.equals("ICONIFIED")) { frameState = Frame.ICONIFIED; } else if (state.equals("MAXIMIZED_HORIZ")) { frameState = Frame.MAXIMIZED_HORIZ; } else if (state.equals("MAXIMIZED_VERT")) { frameState = Frame.MAXIMIZED_VERT; } else if (state.equals("MAXIMIZED_BOTH")) { frameState = Frame.MAXIMIZED_BOTH; } framePos[0] = config.getInt("SessionData.Frame.PosX", 0); framePos[1] = config.getInt("SessionData.Frame.PosY", 0); frameSize[0] = config.getInt("SessionData.Frame.Width", 800); frameSize[1] = config.getInt("SessionData.Frame.Heigth", 600); setFilterStation(config.getString("Configuration.Filters.Station")); setFilterNetwork(config.getString("Configuration.Filters.Network")); setFilterChannel(config.getString("Configuration.Filters.Channel")); setFilterLocation(config.getString("Configuration.Filters.Location")); } catch (NoSuchElementException e) { // do nothing, use defaults logger.error("NoSuchElementException:", e); } } static public XMAXconfiguration getInstance() { AbstractConfiguration.setDefaultListDelimiter(';'); try { if (instance == null) { instance = new XMAXconfiguration(); } } catch (ConfigurationException e) { logger.error("ConfigurationException:", e); } catch (XMAXException e) { logger.error("XMAXException:", e); } catch (TraceViewException e) { logger.error("TraceViewException:", e); } return instance; } /** * Getter of the property OutputPath, see also {@code <OutputPath>} tag in config.xml * * @return Returns the directory to store generated files. */ public String getOutputPath() { return outputPath.replace("." + File.separator, getConfigFileDir()); } /** * Setter of the property outputPath, see also {@code <OutputPath>} tag in config.xml * * @param outputPath * directory to store generated files. */ public void setOutputPath(String outputPath) { this.outputPath = outputPath; } /** * Getter of the property Time interval * * @return time interval to set after initialization and for filtering of source data during * parsing. */ public TimeInterval getTimeInterval() { return ti; } private void setColorModeState(String colorMode, boolean needsave) throws XMAXException{ if(colorMode.toUpperCase().equals("SEGMENT")){ setColorModeState(new ColorModeBySegment()); } else if(colorMode.toUpperCase().equals("GAP")){ setColorModeState(new ColorModeBySegment()); } else if(colorMode.toUpperCase().equals("BW")){ setColorModeState(new ColorModeBySegment()); } else if(colorMode.toUpperCase().equals("GRAY")){ setColorModeState(new ColorModeBySegment()); } else { throw new XMAXException("Illegal color mode marker"); } if(needsave) config.setProperty("Configuration.View.ColorMode", colorMode); } /** * Setter of the property <tt>startTime</tt> * * @param startTime * start time of time interval * @see XMAXconfiguration#getTimeInterval() */ public void setStartTime(Date startTime) throws XMAXException { if (ti == null) { ti = new TimeInterval(startTime, new Date(startTime.getTime() + 24 * 60 * 60 * 1000)); } else { if (startTime.getTime() < ti.getEnd()) { ti = new TimeInterval(startTime, ti.getEndTime()); } else { throw new XMAXException("Start time (" + startTime + ") more then end time (" + ti.getEndTime() + ")"); } } } /** * Setter of the property <tt>endTime</tt> * * @param endTime * start time of time interval * @see XMAXconfiguration#getTimeInterval() */ public void setEndTime(Date endTime) throws XMAXException { if (ti == null) { ti = new TimeInterval(new Date(endTime.getTime() - 24 * 60 * 60 * 1000), endTime); } else { if (endTime.getTime() > ti.getStart()) { ti = new TimeInterval(ti.getStartTime(), endTime); } else { throw new XMAXException("End time (" + endTime + ") less then start time (" + ti.getStartTime() + ")"); } } } /** * Getter of the property qCdataFileName, see also {@code <QCDataFile>} tag in config.xml and * -q command line option. * * @return quality control data file name. */ public String getQCdataFileName() { return qCdataFileName.replace("." + File.separator, getConfigFileDir()); } /** * Setter of the property qCdataFileName, see also {@code <QCDataFile>} tag in config.xml and * -q command line option. * * @param qCdataFileName * quality control data file name. */ public void setQCdataFileName(String qCdataFileName) { this.qCdataFileName = qCdataFileName; } /** * Getter of the property pickPath, see also {@code <PickPath>} tag in config.xml and -p * command line option. * * @return directory name to store picks database. */ public String getPickPath() { return pickPath.replace("." + File.separator, getConfigFileDir()); } /** * Setter of the property pickPath, see also {@code <PickPath>} tag in config.xml and -p * command line option. * * @param pickPath * directory name to store picks database. */ public void setPickPath(String pickPath) { this.pickPath = pickPath; } /** * Getter of the property earthquakeFileMask, see also {@code <EventFileMask>} tag in * config.xml and -k command line option. * * @return wildcarded mask to search earthquake description files. */ public String getEarthquakeFileMask() { return earthquakeFileMask.replace("." + File.separator, getConfigFileDir()); } /** * Getter of the property earthquakeFileMask, see also {@code <EventFileMask>} tag in * config.xml and -k command line option. * * @param earthquakeFileMask * wildcarded mask to search earthquake description files. */ public void setEarthquakeFileMask(String earthquakeFileMask) { this.earthquakeFileMask = earthquakeFileMask; } /** * @return last selected in the file chooser directory, see also {@code <ExportDir>} tag in config.xml */ public String getUserDir(String type) { return userDirectories.get(type); } /** * @param dir * last selected in the file chooser directory, see also {@code <ExportDir>} tag in * config.xml */ public void setUserDir(String type, String dir) { if ((getUserDir(type) == null) || !getUserDir(type).equals(dir)) { config.clearProperty("SessionData.UserDir." + type); if (dir != null) { userDirectories.put(type, dir); config.addProperty("SessionData.UserDir." + type, dir); } save(); } } public Point getFramePos() { return new Point(framePos[0], framePos[1]); } public Dimension getFrameSize() { return new Dimension(frameSize[0], frameSize[1]); } public int getFrameExtendedState() { return frameState; } public void setFrameState(int extendedState, int posX, int posY, int width, int heigth) { boolean needsave = false; String state = ""; if (extendedState != frameState) { frameState = extendedState; switch (frameState) { case Frame.NORMAL: state = "NORMAL"; break; case Frame.ICONIFIED: state = "ICONIFIED"; break; case Frame.MAXIMIZED_HORIZ: state = "MAXIMIZED_HORIZ"; break; case Frame.MAXIMIZED_VERT: state = "MAXIMIZED_VERT"; break; case Frame.MAXIMIZED_BOTH: state = "MAXIMIZED_BOTH"; break; default: state = "MAXIMIZED_BOTH"; } config.setProperty("SessionData.Frame.State", state); needsave = true; } if (posX != framePos[0]) { if (posX < 0) { framePos[0] = 0; } else { framePos[0] = posX; } config.setProperty("SessionData.Frame.PosX", framePos[0]); needsave = true; } if (posY != framePos[1]) { if (posY < 0) { framePos[1] = 0; } else { framePos[1] = posY; } config.setProperty("SessionData.Frame.PosY", framePos[1]); needsave = true; } if (width != frameSize[0]) { frameSize[0] = width; config.setProperty("SessionData.Frame.Width", width); needsave = true; } if (heigth != frameSize[1]) { frameSize[1] = heigth; config.setProperty("SessionData.Frame.Heigth", heigth); needsave = true; } if (needsave) { save(); } } /** * @return flag if we see status bar at the bottom of main frame */ public boolean getShowStatusBar() { return showStatusBar; } /** * @param ssb * flag if we see status bar at the bottom of main frame */ public void setShowStatusBar(boolean ssb) { this.showStatusBar = ssb; } /** * @return flag if we see command buttons panel in the main frame */ public boolean getShowCommandButtons() { return showCommandButtons; } /** * @param scb * flag if we see command buttons panel in the main frame */ public void setShowCommandButtons(boolean scb) { this.showCommandButtons = scb; } /** * @return if true, we see command buttons panel at the top of main frame, otherwise we see it * at the bottom. */ public boolean getShowCommandButtonsTop() { return showCommandButtonsTop; } /** * @param scbt * if true, we see command buttons panel at the top of main frame, otherwise we see * it at the bottom. */ public void setShowCommandButtonsTop(boolean scbt) { this.showCommandButtonsTop = scbt; } /** * Getter of the property <tt>logFile</tt> * * @return the log file name. */ public String getLogFile() { return logFile; } /** * Setter of the property <tt>logFile</tt> * * @param logFile * the log file name. */ public void setLogFile(String logFile) { this.logFile = logFile; } /** * Get HTML pattern to generate blank HTML report. First looks in the "pattern.html" file, if * not found returns default pattern */ public String getHTMLpattern() { File file = new File("pattern.html"); if (file.exists()) { try { FileInputStream fis = new FileInputStream(file); FileChannel fch = fis.getChannel(); MappedByteBuffer mbf = fch.map(FileChannel.MapMode.READ_ONLY, 0, fch.size()); byte[] barray = new byte[(int) (fch.size())]; mbf.get(barray); fis.close(); return new String(barray); } catch (FileNotFoundException e) { logger.error("Can't get html pattern: ", e); return getDefaultHTMLPattern(); } catch (IOException e) { logger.error("Can't get html pattern: ", e); return getDefaultHTMLPattern(); } } else { return getDefaultHTMLPattern(); } } public SubnodeConfiguration getConfigurationAt(String node){ return config.configurationAt(node); } public void save(){ try { config.save(confFileName); } catch (ConfigurationException e) { logger.error("can't save configuration to file " + confFileName + ": ", e); } } }