source: src/main/java/weka/core/Debug.java @ 19

Last change on this file since 19 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 42.1 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * Debug.java
19 * Copyright (C) 2006 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.core;
23
24import java.io.BufferedWriter;
25import java.io.FileWriter;
26import java.io.PrintWriter;
27import java.io.Serializable;
28import java.io.StringWriter;
29import java.lang.management.ManagementFactory;
30import java.lang.management.ThreadMXBean;
31import java.text.SimpleDateFormat;
32import java.util.Date;
33import java.util.logging.FileHandler;
34import java.util.logging.Handler;
35import java.util.logging.Level;
36import java.util.logging.Logger;
37import java.util.logging.SimpleFormatter;
38
39/**
40 * A helper class for debug output, logging, clocking, etc.
41 *
42 * @author  fracpete (fracpete at waikato dot ac dot nz)
43 * @version $Revision: 5953 $
44 */
45public class Debug
46  implements Serializable, RevisionHandler {
47
48  /** for serialization */
49  private static final long serialVersionUID = 66171861743328020L;
50 
51  /** the log level All */
52  public final static Level ALL = Level.ALL;
53  /** the log level Vonfig */
54  public final static Level CONFIG = Level.CONFIG;
55  /** the log level Fine */
56  public final static Level FINE = Level.FINE;
57  /** the log level Finer */
58  public final static Level FINER = Level.FINER;
59  /** the log level Finest */
60  public final static Level FINEST = Level.FINEST;
61  /** the log level Info */
62  public final static Level INFO = Level.INFO;
63  /** the log level Off - i.e., no logging */
64  public final static Level OFF = Level.OFF;
65  /** the log level Severe */
66  public final static Level SEVERE = Level.SEVERE;
67  /** the log level Warning */
68  public final static Level WARNING = Level.WARNING;
69
70  /** whether logging is enabled */
71  protected boolean m_Enabled = true;
72 
73  /** for logging */
74  protected Log m_Log;
75 
76  /** for clocking */
77  protected Clock m_Clock = new Clock();
78 
79  /**
80   * A little helper class for clocking and outputting times. It measures the
81   * CPU time if possible, otherwise it's just based on the system time. In
82   * case one just wants to measure time (e.g., database queries don't take up
83   * much CPU time, but still might take a long time to finish), then one can
84   * disable the use of CPU time as well.
85   *
86   * @author FracPete (fracpete at waikato dot ac dot nz)
87   * @version $Revision: 5953 $
88   * @see ThreadMXBean#isThreadCpuTimeEnabled()
89   */
90  public static class Clock 
91    implements Serializable, RevisionHandler {
92   
93    /** for serialization */
94    private static final long serialVersionUID = 4622161807307942201L;
95   
96    /** the output format in milli-seconds */
97    public final static int FORMAT_MILLISECONDS = 0;
98   
99    /** the output format in seconds, with fraction of msecs */
100    public final static int FORMAT_SECONDS = 1;
101   
102    /** the output format in hours:minutes:seconds, with fraction of msecs */
103    public final static int FORMAT_HHMMSS = 2;
104   
105    /** the output formats */
106    public static final Tag[] TAGS_FORMAT = {
107      new Tag(FORMAT_MILLISECONDS, "milli-seconds"),
108      new Tag(FORMAT_SECONDS, "seconds"),
109      new Tag(FORMAT_HHMMSS, "hh:mm:ss")
110    };
111   
112    /** the format of the output */
113    public int m_OutputFormat = FORMAT_SECONDS;
114   
115    /** the start time */
116    protected long m_Start;
117   
118    /** the end time */
119    protected long m_Stop;
120   
121    /** whether the time is still clocked */
122    protected boolean m_Running;
123   
124    /** the thread ID */
125    protected long m_ThreadID;
126   
127    /** whether the system can measure the CPU time */
128    protected boolean m_CanMeasureCpuTime;
129   
130    /** whether to use the CPU time (by default TRUE) */
131    protected boolean m_UseCpuTime;
132   
133    /** the thread monitor, if the system can measure the CPU time */
134    protected transient ThreadMXBean m_ThreadMonitor;
135   
136    /**
137     * automatically starts the clock with FORMAT_SECONDS format and CPU
138     * time if available
139     *
140     * @see             #m_OutputFormat
141     */
142    public Clock() {
143      this(true);
144    }
145   
146    /**
147     * automatically starts the clock with the given output format and CPU
148     * time if available
149     *
150     * @param format    the output format
151     * @see             #m_OutputFormat
152     */
153    public Clock(int format) {
154      this(true, format);
155    }
156   
157    /**
158     * starts the clock depending on <code>start</code> immediately with the
159     * FORMAT_SECONDS output format and CPU time if available
160     *
161     * @param start     whether to start the clock immediately
162     * @see             #m_OutputFormat
163     */
164    public Clock(boolean start) {
165      this(start, FORMAT_SECONDS);
166    }
167   
168    /**
169     * starts the clock depending on <code>start</code> immediately, using
170     * CPU time if available
171     *
172     * @param start     whether to start the clock immediately
173     * @param format    the format
174     * @see             #m_OutputFormat
175     */
176    public Clock(boolean start, int format) {
177      m_Running    = false;
178      m_Start      = 0;
179      m_Stop       = 0;
180      m_UseCpuTime = true;
181      setOutputFormat(format);
182
183      if (start)
184        start();
185    }
186   
187    /**
188     * initializes the clocking, ensure to get the correct thread ID.
189     */
190    protected void init() {
191      m_ThreadMonitor = null;
192      m_ThreadMonitor = getThreadMonitor();
193
194      // can we measure cpu time?
195      m_CanMeasureCpuTime = m_ThreadMonitor.isThreadCpuTimeSupported();
196    }
197   
198    /**
199     * whether the measurement is based on the msecs returned from the System
200     * class or on the more accurate CPU time. Also depends on whether the
201     * usage of the CPU time was disabled or enabled.
202     *
203     * @return          true if the more accurate CPU time of the thread is
204     *                  used and the use of CPU time hasn't been disabled
205     * @see System#currentTimeMillis()
206     * @see ThreadMXBean#isThreadCpuTimeEnabled()
207     * @see #getUseCpuTime()
208     */
209    public boolean isCpuTime() {
210      return m_UseCpuTime && m_CanMeasureCpuTime;
211    }
212
213    /**
214     * enables/disables the use of CPU time (if measurement of CPU time is
215     * available). The actual use of CPU time still depends on whether the
216     * system supports it. Resets the current timer, if running.
217     *
218     * @param value     if true the CPU time is used (if possible)
219     */
220    public void setUseCpuTime(boolean value) {
221      m_UseCpuTime = value;
222     
223      // we have to re-initialize the start time, otherwise we get bogus
224      // results
225      if (m_Running) {
226        stop();
227        start();
228      }
229    }
230
231    /**
232     * returns whether the use of CPU is time is enabled/disabled (regardless
233     * whether the system supports it or not)
234     *
235     * @return          true the CPU time is used (if possible)
236     */
237    public boolean getUseCpuTime() {
238      return m_UseCpuTime;
239    }
240   
241    /**
242     * Returns a new thread monitor if the current one is null (e.g., due to
243     * serialization) or the currently set one. The thread ID is also updated
244     * if necessary.
245     *
246     * @return          the thread monitor to use
247     */
248    protected ThreadMXBean getThreadMonitor() {
249      if (m_ThreadMonitor == null) {
250        m_ThreadMonitor = ManagementFactory.getThreadMXBean();
251        if (!m_ThreadMonitor.isThreadCpuTimeEnabled())
252          m_ThreadMonitor.setThreadCpuTimeEnabled(true);
253        m_ThreadID = Thread.currentThread().getId();
254      }
255     
256      return m_ThreadMonitor;
257    }
258   
259    /**
260     * returns the current time in msec
261     *
262     * @return          the current time
263     */
264    protected long getCurrentTime() {
265      long      result;
266     
267      if (isCpuTime())
268        result = getThreadMonitor().getThreadUserTime(m_ThreadID) / 1000000;
269      else
270        result = System.currentTimeMillis();
271     
272      return result;
273    }
274   
275    /**
276     * saves the current system time (or CPU time) in msec as start time
277     *
278     * @see       #m_Start
279     */
280    public void start() {
281      // make sure that we get the right thread ID!
282      init();
283
284      m_Start   = getCurrentTime();
285      m_Stop    = m_Start;
286      m_Running = true;
287    }
288   
289    /**
290     * saves the current system (or CPU time) in msec as stop time
291     *
292     * @see       #m_Stop
293     */
294    public void stop() {
295      m_Stop    = getCurrentTime();
296      m_Running = false;
297    }
298   
299    /**
300     * returns the start time
301     *
302     * @return  the start time
303     */
304    public long getStart() {
305      return m_Start;
306    }
307   
308    /**
309     * returns the stop time or, if still running, the current time
310     *
311     * @return  the stop time
312     */
313    public long getStop() {
314      long      result;
315     
316      if (isRunning())
317        result = getCurrentTime();
318      else
319        result = m_Stop;
320     
321      return result;
322    }
323   
324    /**
325     * whether the time is still being clocked
326     *
327     * @return          true if the time is still being clocked
328     */
329    public boolean isRunning() {
330      return m_Running;
331    }
332   
333    /**
334     * sets the format of the output
335     *
336     * @param value       the format of the output
337     * @see               #m_OutputFormat
338     */
339    public void setOutputFormat(int value) {
340      if (value == FORMAT_MILLISECONDS)
341        m_OutputFormat = value;
342      else if (value == FORMAT_SECONDS)
343        m_OutputFormat = value;
344      else if (value == FORMAT_HHMMSS)
345        m_OutputFormat = value;
346      else
347        System.out.println("Format '" + value + "' is not recognized!");
348    }
349   
350    /**
351     * returns the output format
352     *
353     * @return          the output format
354     * @see             #m_OutputFormat
355     */
356    public int getOutputFormat() {
357      return m_OutputFormat;
358    }
359   
360    /**
361     * returns the elapsed time, getStop() - getStart(), as string
362     *
363     * @return  the elapsed time as string
364     * @see       #getStart()
365     * @see       #getStop()
366     */
367    public String toString() {
368      String    result;
369      long      elapsed;
370      long      hours;
371      long      mins;
372      long      secs;
373      long      msecs;
374     
375      result  = "";
376      elapsed = getStop() - getStart();
377     
378      switch (getOutputFormat()) {
379        case FORMAT_HHMMSS:
380          hours   = elapsed / (3600 * 1000);
381          elapsed = elapsed % (3600 * 1000);
382          mins    = elapsed / (60 * 1000);
383          elapsed = elapsed % (60 * 1000);
384          secs    = elapsed / 1000;
385          msecs   = elapsed % 1000;
386         
387          if (hours > 0)
388            result += "" + hours + ":";
389         
390          if (mins < 10)
391            result += "0" + mins + ":";
392          else
393            result += ""  + mins + ":";
394         
395          if (secs < 10)
396            result += "0" + secs + ".";
397          else
398            result += "" + secs + ".";
399         
400          result += Utils.doubleToString(
401              (double) msecs / (double) 1000, 3).replaceAll(".*\\.", "");
402          break;
403         
404        case FORMAT_SECONDS:
405          result = Utils.doubleToString((double) elapsed / (double) 1000, 3) + "s";
406          break;
407         
408        case FORMAT_MILLISECONDS:
409          result = "" + elapsed + "ms";
410          break;
411         
412        default:
413          result = "<unknown time format>";
414      }
415     
416      return result;
417    }
418   
419    /**
420     * Returns the revision string.
421     *
422     * @return          the revision
423     */
424    public String getRevision() {
425      return RevisionUtils.extract("$Revision: 5953 $");
426    }
427  }
428 
429  /**
430   * A class that can be used for timestamps in files, The toString() method
431   * simply returns the associated Date object in a timestamp format. For
432   * formatting options, see java.text.SimpleDateFormat.
433   *
434   * @author FracPete (fracpete at waikato dot ac dot nz)
435   * @version $Revision: 5953 $
436   * @see SimpleDateFormat
437   */
438  public static class Timestamp
439    implements Serializable, RevisionHandler {
440   
441    /** for serialization */
442    private static final long serialVersionUID = -6099868388466922753L;
443
444    /** the default format */
445    public final static String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
446   
447    /** the actual date */
448    protected Date m_Stamp;
449   
450    /** the format of the timestamp */
451    protected String m_Format;
452   
453    /** handles the format of the output */
454    protected SimpleDateFormat m_Formatter;
455   
456    /**
457     * creates a timestamp with the current date and time and the default
458     * format.
459     */
460    public Timestamp() {
461      this(DEFAULT_FORMAT);
462    }
463   
464    /**
465     * creates a timestamp with the current date and time and the specified
466     * format.
467     *
468     * @param format    the format of the timestamp
469     * @see             SimpleDateFormat
470     */
471    public Timestamp(String format) {
472      this(new Date(), format);
473    }
474   
475    /**
476     * creates a timestamp with the given date and the default format.
477     *
478     * @param stamp     the associated date/time for the timestamp
479     */
480    public Timestamp(Date stamp) {
481      this(stamp, DEFAULT_FORMAT);
482    }
483   
484    /**
485     * creates a timestamp with the given date and format.
486     *
487     * @param stamp     the associated date/time for the timestamp
488     * @param format    the format of the timestamp
489     * @see             SimpleDateFormat
490     */
491    public Timestamp(Date stamp, String format) {
492      super();
493     
494      m_Stamp = stamp;
495      setFormat(format);
496    }
497   
498    /**
499     * sets the format for the timestamp
500     *
501     * @param value     the format string
502     * @see             SimpleDateFormat
503     */
504    public void setFormat(String value) {
505      try {
506        m_Formatter = new SimpleDateFormat(value);
507        m_Format    = value;
508      }
509      catch (Exception e) {
510        m_Formatter = new SimpleDateFormat(DEFAULT_FORMAT);
511        m_Format    = DEFAULT_FORMAT;
512      }
513    }
514   
515    /**
516     * returns the current timestamp format
517     *
518     * @return          the current format
519     */
520    public String getFormat() {
521      return m_Format;
522    }
523   
524    /**
525     * returns the associated date/time
526     *
527     * @return          the timestamp value
528     */
529    public Date getStamp() {
530      return m_Stamp;
531    }
532   
533    /**
534     * returns the timestamp as string in the specified format
535     *
536     * @return          the timestamp as string
537     */
538    public String toString() {
539      return m_Formatter.format(getStamp());
540    }
541   
542    /**
543     * Returns the revision string.
544     *
545     * @return          the revision
546     */
547    public String getRevision() {
548      return RevisionUtils.extract("$Revision: 5953 $");
549    }
550  }
551 
552  /**
553   * A little, simple helper class for logging stuff. Uses simple file access
554   * and not the java.util.logging stuff (see Log for that). Uses the
555   * writeToFile methods of the Debug class.
556   *
557   * @see Debug.Log
558   * @see Debug#writeToFile(String, String)
559   * @see Debug#writeToFile(String, String, boolean)
560   */
561  public static class SimpleLog 
562    implements Serializable, RevisionHandler {
563   
564    /** for serialization */
565    private static final long serialVersionUID = -2671928223819510830L;
566   
567    /** the file to write to (if null then only stdout is used) */
568    protected String m_Filename = null;
569   
570    /**
571     * default constructor, uses only stdout
572     */
573    public SimpleLog() {
574      this(null);
575    }
576   
577    /**
578     * Creates a logger that writes into the specified file. Appends to the
579     * file by default.
580     *
581     * @param filename  the file to write to, if null then only stdout is used
582     */
583    public SimpleLog(String filename) {
584      this(filename, true);
585    }
586   
587    /**
588     * Creates a logger that writes into the specified file. Appends to the
589     * file by default.
590     *
591     * @param filename  the file to write to, if null then only stdout is used
592     * @param append    if false, the file will be deleted first
593     */
594    public SimpleLog(String filename, boolean append) {
595      super();
596     
597      m_Filename = filename;
598     
599      Debug.writeToFile(m_Filename, "--> Log started", append);
600    }
601   
602    /**
603     * returns the filename of the log, can be null
604     *
605     * @return          the filename of the log
606     */
607    public String getFilename() {
608      return m_Filename;
609    }
610   
611    /**
612     * logs the given message to the file
613     *
614     * @param message   the message to log
615     */
616    public void log(String message) {
617      String    log;
618     
619      log = new Timestamp() + " " + message;
620     
621      if (getFilename() != null)
622        Debug.writeToFile(getFilename(), log);
623
624      System.out.println(log);
625    }
626   
627    /**
628     * a convenience method for dumping the current system info in the
629     * log file
630     *
631     * @see SystemInfo
632     */
633    public void logSystemInfo() {
634      log("SystemInfo:\n" + new SystemInfo().toString());
635    }
636   
637    /**
638     * returns a string representation of the logger
639     *
640     * @return          a string representation of the logger
641     */
642    public String toString() {
643      String    result;
644     
645      result =   "Filename: " + getFilename();
646     
647      return result;
648    }
649   
650    /**
651     * Returns the revision string.
652     *
653     * @return          the revision
654     */
655    public String getRevision() {
656      return RevisionUtils.extract("$Revision: 5953 $");
657    }
658  }
659 
660  /**
661   * A helper class for logging stuff. Uses the java.util.logging
662   * package. If this approach seems an "overkill" (it can create quite a few
663   * log files if used in different threads), one can use the
664   * Debug.SimpleLog class.
665   *
666   * @author FracPete (fracpete at waikato dot ac dot nz)
667   * @version $Revision: 5953 $
668   * @see Debug.SimpleLog
669   */
670  public static class Log
671    implements Serializable, RevisionHandler {
672   
673    /** for serialization */
674    private static final long serialVersionUID = 1458435732111675823L;
675
676    /** the actual logger, if null only stdout is used */
677    protected transient Logger m_Logger = null;
678   
679    /** the filename, if any */
680    protected String m_Filename = null;
681   
682    /** the size of the file (in bytes) */
683    protected int m_Size;
684   
685    /** the number of files for rotating the logs */
686    protected int m_NumFiles;
687
688    /** whether the initialization of the logger failed */
689    protected boolean m_LoggerInitFailed = false;
690   
691    /**
692     * default constructor, uses only stdout
693     */
694    public Log() {
695      this(null);
696    }
697   
698    /**
699     * creates a logger that logs into the specified file, if null then only
700     * stdout is used. It uses 1,000,000 bytes for file size and 1 file.
701     *
702     * @param filename  the file to log into
703     */
704    public Log(String filename) {
705      this(filename, 1000000, 1);
706    }
707   
708    /**
709     * creates a logger that logs into the specified file, if null then only
710     * stdout is used.
711     *
712     * @param filename  the file to log into
713     * @param size      the size of the files in bytes
714     * @param numFiles  the number of files for rotating
715     */
716    public Log(String filename, int size, int numFiles) {
717      m_Filename = filename;
718      m_Size     = size;
719      m_NumFiles = numFiles;
720    }
721   
722    /**
723     * initializes and returns the logger if necessary (e.g., due to
724     * serialization).
725     *
726     * @return          the logger, can be null, e.g., if no filename provided
727     */
728    protected Logger getLogger() {
729      if ( (m_Logger == null) && (!m_LoggerInitFailed) ) {
730        if (m_Filename != null) {
731          m_Logger = Logger.getLogger(m_Filename);
732          Handler fh = null;
733          try{       
734            fh = new FileHandler(m_Filename, m_Size, m_NumFiles);
735            fh.setFormatter(new SimpleFormatter());
736            m_Logger.addHandler(fh);     
737            m_LoggerInitFailed = false;
738          }
739          catch(Exception e) {
740            System.out.println("Cannot init fileHandler for logger:" + e.toString());
741            m_Logger = null;
742            m_LoggerInitFailed = true;
743          } 
744        }
745      }
746     
747      return m_Logger;
748    }
749   
750    /**
751     * turns the string representing a level, e.g., "FINE" or "ALL" into
752     * the corresponding level (case-insensitive). The default is ALL.
753     *
754     * @param level     the string to return a level for
755     * @return          the corresponding level or the default
756     */
757    public static Level stringToLevel(String level) {
758      Level     result;
759     
760      if (level.equalsIgnoreCase("ALL"))
761        result = ALL;
762      else if (level.equalsIgnoreCase("CONFIG"))
763        result = CONFIG;
764      else if (level.equalsIgnoreCase("FINE"))
765        result = FINE;
766      else if (level.equalsIgnoreCase("FINER"))
767        result = FINER;
768      else if (level.equalsIgnoreCase("FINEST"))
769        result = FINEST;
770      else if (level.equalsIgnoreCase("INFO"))
771        result = INFO;
772      else if (level.equalsIgnoreCase("OFF"))
773        result = OFF;
774      else if (level.equalsIgnoreCase("SEVERE"))
775        result = SEVERE;
776      else if (level.equalsIgnoreCase("WARNING"))
777        result = WARNING;
778      else
779        result = ALL;
780     
781      return result;
782    }
783   
784    /**
785     * returns the filename of the log, can be null
786     *
787     * @return          the filename of the log
788     */
789    public String getFilename() {
790      return m_Filename;
791    }
792   
793    /**
794     * returns the size of the files
795     *
796     * @return          the size of a file
797     */
798    public int getSize() {
799      return m_Size;
800    }
801   
802    /**
803     * returns the number of files being used
804     *
805     * @return          the number of files
806     */
807    public int getNumFiles() {
808      return m_NumFiles;
809    }
810
811    /**
812     * logs the given message
813     *
814     * @param level     the level of severity
815     * @param message   the message to log
816     */
817    public void log(Level level, String message) {
818      log(level, "", message);
819    }
820   
821    /**
822     * prints the given message with the specified level
823     *
824     * @param level     the level of logging
825     * @param sourceclass       the class that logs the message
826     * @param message   the message to print
827     */
828    public void log(Level level, String sourceclass, String message) {
829      log(level, sourceclass, "", message);
830    }
831   
832    /**
833     * prints the given message with the specified level
834     *
835     * @param level             the level of logging
836     * @param sourceclass               the class that logs the message
837     * @param sourcemethod      the method that logs the message
838     * @param message           the message to print
839     */
840    public void log(Level level, String sourceclass, String sourcemethod, String message) {
841      Logger    logger;
842     
843      logger = getLogger();
844     
845      if (logger != null)
846        logger.logp(level, sourceclass, sourcemethod, message);
847      else
848        System.out.println(message);
849    }
850   
851    /**
852     * a convenience method for dumping the current system info in the
853     * log file
854     *
855     * @see SystemInfo
856     */
857    public void logSystemInfo() {
858      log(INFO, "SystemInfo:\n" + new SystemInfo().toString());
859    }
860   
861    /**
862     * returns a string representation of the logger
863     *
864     * @return          a string representation of the logger
865     */
866    public String toString() {
867      String    result;
868     
869      result =   "Filename: " + getFilename() + ", "
870               + "Size: " + getSize() + ", "
871               + "# Files: " + getNumFiles();
872     
873      return result;
874    }
875   
876    /**
877     * Returns the revision string.
878     *
879     * @return          the revision
880     */
881    public String getRevision() {
882      return RevisionUtils.extract("$Revision: 5953 $");
883    }
884  }
885
886  /**
887   * This extended Random class enables one to print the generated random
888   * numbers etc., before they are returned. It can either use stdout (default)
889   * for outputting the logging information or a Log object (level is then
890   * INFO).
891   *
892   * @author  FracPete (fracpete at waikato dot ac dot nz)
893   * @version $Revision: 5953 $
894   */
895  public static class Random
896    extends java.util.Random
897    implements Serializable, RevisionHandler {
898
899    /** for serialization */
900    private static final long serialVersionUID = 1256846887618333956L;
901
902    /** whether to output debug information */
903    protected boolean m_Debug = false;
904
905    /** the unique ID for this number generator */
906    protected long m_ID;
907   
908    /** for keeping track of unique IDs */
909    protected static long m_CurrentID;
910   
911    /** the log to use for outputting the data, otherwise just stdout */
912    protected Log m_Log = null;
913   
914    /**
915     * Creates a new random number generator. With no debugging.
916     */
917    public Random() {
918      this(false);
919    }
920
921    /**
922     * Creates a new random number generator using a single long seed.
923     * With no debugging
924     *
925     * @param seed      the seed value
926     */
927    public Random(long seed) {
928      this(seed, false);
929    }
930
931    /**
932     * Creates a new random number generator. With optional debugging.
933     *
934     * @param debug     if true, debugging output is enabled
935     */
936    public Random(boolean debug) {
937      super();
938      setDebug(debug);
939      m_ID = nextID();
940      if (getDebug())
941        printStackTrace();
942    }
943
944    /**
945     * Creates a new random number generator using a single long seed.
946     * With optional debugging
947     *
948     * @param seed      the seed value
949     * @param debug     if true, debugging output is enabled
950     */
951    public Random(long seed, boolean debug) {
952      super(seed);
953      setDebug(debug);
954      m_ID = nextID();
955      if (getDebug())
956        printStackTrace();
957    }
958
959    /**
960     * sets whether to print the generated random values or not
961     *
962     * @param value     if true debugging output is enabled
963     */
964    public void setDebug(boolean value) {
965      m_Debug = value;
966    }
967
968    /**
969     * returns whether to print the generated random values or not
970     *
971     * @return          true if debugging output is enabled
972     */
973    public boolean getDebug() {
974      return m_Debug;
975    }
976   
977    /**
978     * the log to use, if it is null then stdout is used
979     *
980     * @param value     the log to use
981     */
982    public void setLog(Log value) {
983      m_Log = value;
984    }
985   
986    /**
987     * the currently used log, if null then stdout is used for outputting
988     * the debugging information
989     *
990     * @return          the log, can be null
991     */
992    public Log getLog() {
993      return m_Log;
994    }
995
996    /**
997     * returns the next unique ID for a number generator
998     *
999     * @return          the next unique ID
1000     */
1001    protected static long nextID() {
1002      m_CurrentID++;
1003     
1004      return m_CurrentID;
1005    }
1006
1007    /**
1008     * returns the unique ID of this number generator
1009     *
1010     * @return          the unique ID of this number generator
1011     */
1012    public long getID() {
1013      return m_ID;
1014    }
1015
1016    /**
1017     * prints the given message only if m_Debug is TRUE
1018     *
1019     * @param msg       the message to print
1020     * @see             #m_Debug
1021     */
1022    protected void println(String msg) {
1023      if (getDebug()) {
1024        if (getLog() != null)
1025          getLog().log(Level.INFO, m_ID + ": " + msg);
1026        else
1027          System.out.println(m_ID + ": " + msg);
1028      }
1029    }
1030
1031    /**
1032     * prints the current stacktrace
1033     */
1034    public void printStackTrace() {
1035      Throwable         t;
1036      StringWriter      writer;
1037
1038      writer = new StringWriter();
1039     
1040      // generate stacktrace
1041      t = new Throwable();
1042      t.fillInStackTrace();
1043      t.printStackTrace(new PrintWriter(writer));
1044
1045      println(writer.toString());
1046    }
1047
1048    /**
1049     * Returns the next pseudorandom, uniformly distributed boolean value from
1050     * this random number generator's sequence.
1051     *
1052     * @return          random boolean
1053     */
1054    public boolean nextBoolean() {
1055      boolean result = super.nextBoolean();
1056      println("nextBoolean=" + result);
1057      return result;
1058    }
1059
1060    /**
1061     * Generates random bytes and places them into a user-supplied byte array.
1062     *
1063     * @param bytes     array to fill with random bytes
1064     */
1065    public void nextBytes(byte[] bytes) {
1066      super.nextBytes(bytes);
1067      println("nextBytes=" + Utils.arrayToString(bytes));
1068    }
1069
1070    /**
1071     * Returns the next pseudorandom, uniformly distributed double value between
1072     * 0.0 and 1.0 from this random number generator's sequence.
1073     *
1074     * @return          random double
1075     */
1076    public double nextDouble() {
1077      double result = super.nextDouble();
1078      println("nextDouble=" + result);
1079      return result;
1080    }
1081
1082    /**
1083     * Returns the next pseudorandom, uniformly distributed float  value between
1084     * 0.0 and 1.0 from this random number generator's sequence.
1085     *
1086     * @return          random float
1087     */
1088    public float nextFloat() {
1089      float result = super.nextFloat();
1090      println("nextFloat=" + result);
1091      return result;
1092    }
1093
1094    /**
1095     * Returns the next pseudorandom, Gaussian ("normally") distributed double
1096     * value with mean 0.0 and standard deviation 1.0 from this random number
1097     * generator's sequence.
1098     *
1099     * @return          random double, gaussian distributed
1100     */
1101    public double nextGaussian() {
1102      double result = super.nextGaussian();
1103      println("nextGaussian=" + result);
1104      return result;
1105    }
1106
1107    /**
1108     * Returns the next pseudorandom, uniformly distributed int  value from this
1109     * random number generator's sequence.
1110     *
1111     * @return          random int
1112     */
1113    public int nextInt() {
1114      int result = super.nextInt();
1115      println("nextInt=" + result);
1116      return result;
1117    }
1118
1119    /**
1120     * Returns a pseudorandom, uniformly distributed int value between 0
1121     * (inclusive) and the specified value (exclusive), drawn from this random
1122     * number generator's sequence.
1123     *
1124     * @param n         the upper limit (exclusive)
1125     * @return          random int
1126     */
1127    public int nextInt(int n) {
1128      int result = super.nextInt(n);
1129      println("nextInt(" + n + ")=" + result);
1130      return result;
1131    }
1132
1133    /**
1134     * Returns the next pseudorandom, uniformly distributed long  value from this
1135     * random number generator's sequence.
1136     *
1137     * @return          random long
1138     */
1139    public long nextLong() {
1140      long result = super.nextLong();
1141      println("nextLong=" + result);
1142      return result;
1143    }
1144
1145    /**
1146     * Sets the seed of this random number generator using a single long seed.
1147     *
1148     * @param seed      the seed value
1149     */
1150    public void setSeed(long seed) {
1151      super.setSeed(seed);
1152      println("setSeed(" + seed + ")");
1153    }
1154
1155    /**
1156     * returns a string representation of this number generator
1157     *
1158     * @return          a string representation
1159     */
1160    public String toString() {
1161      return this.getClass().getName() + ": " + getID();
1162    }
1163   
1164    /**
1165     * Returns the revision string.
1166     *
1167     * @return          the revision
1168     */
1169    public String getRevision() {
1170      return RevisionUtils.extract("$Revision: 5953 $");
1171    }
1172  }
1173  /**
1174   * contains debug methods
1175   *
1176   * @author Gabi Schmidberger (gabi at cs dot waikato dot ac dot nz)
1177   * @version $Revision: 5953 $
1178   */
1179  public static class DBO 
1180    implements Serializable, RevisionHandler {
1181
1182    /** for serialization */
1183    static final long serialVersionUID = -5245628124742606784L; 
1184
1185    /** enables/disables output of debug information */
1186    public boolean m_verboseOn = false;
1187
1188    /** range of outputtyp */
1189    public Range m_outputTypes = new Range();
1190
1191    /**
1192     * Set the verbose on flag on
1193     */
1194    public void setVerboseOn() {
1195      m_verboseOn = true;
1196    }
1197
1198    /**
1199     * Initialize ranges, upper limit must be set
1200     *
1201     * @param upper upper limit
1202     */
1203    public void initializeRanges(int upper) {
1204      m_outputTypes.setUpper(upper);
1205    }
1206
1207    /**
1208     * Return true if the outputtype is set
1209     *
1210     * @param num value that is reserved for a specific outputtype
1211     * @return return true if the output type is set
1212     */
1213    public boolean outputTypeSet(int num) {
1214      return (m_outputTypes.isInRange(num));
1215    }
1216
1217     /**
1218     * Return true if the debug level is set
1219     * same method as outpuTypeSet but better name
1220     *
1221     * @param num value that is reserved for a specific outputtype
1222     * @return return true if the debug level is set
1223     */
1224    public boolean dl(int num) {
1225      return (outputTypeSet(num));
1226    }
1227
1228   /**
1229     * Switches the outputs on that are requested from the option O
1230     *
1231     * @param list list of integers, all are used for an output type
1232     */
1233    public void setOutputTypes(String list) {
1234      if (list.length() > 0) {
1235        m_verboseOn = true; 
1236
1237        m_outputTypes.setRanges(list);
1238        m_outputTypes.setUpper(30);
1239      }
1240    }
1241
1242    /**
1243     * Gets the current output type selection
1244     *
1245     * @return a string containing a comma separated list of ranges
1246     */
1247    public String getOutputTypes() {
1248      return m_outputTypes.getRanges();
1249    }
1250
1251    /**
1252     * prints out text + endofline if verbose is on.
1253     * helps to make debug output commands more visible in text
1254     *
1255     * @param text the text to print
1256     */
1257    public void dpln(String text) {
1258      if (m_verboseOn) {
1259        System.out.println(text);
1260      }
1261    } 
1262
1263    /**
1264     * prints out text + endofline but only if parameter debug type is set.
1265     * helps to make debug output commands more visible in text
1266     *
1267     * @param debugType the type of the output
1268     * @param text the text to print
1269     */
1270    public void dpln(int debugType, String text) {
1271      if (outputTypeSet(debugType)) {
1272        System.out.println(text);
1273      }
1274    } 
1275
1276     /**
1277     * prints out text  if verbose is on.
1278     * helps to make debug output commands more visible in text
1279     *
1280     * @param text the text to print
1281     */
1282    public void dp(String text) {
1283      if (m_verboseOn) {
1284        System.out.print(text);
1285      }
1286    } 
1287
1288   /**
1289     * prints out text but only if debug level is set.
1290     * helps to make debug output commands more visible in text
1291     *
1292     * @param debugType the type of the output
1293     * @param text the text to print
1294     */
1295    public void dp(int debugType, String text) {
1296     if (outputTypeSet(debugType)) {
1297        System.out.print(text);
1298      }
1299    } 
1300
1301    /**
1302     * prints out text + endofline.
1303     * helps to make debug output commands more visible in text
1304     *
1305     * @param text the text to print
1306     */
1307    public static void pln(String text) {
1308      System.out.println(text);
1309    } 
1310
1311    /**
1312     * prints out text.
1313     * helps to make debug output commands more visible in text
1314     *
1315     * @param text the text to print
1316     */
1317    public static void p (String text) {
1318      System.out.print(text);
1319    } 
1320   
1321    /**
1322     * Returns the revision string.
1323     *
1324     * @return          the revision
1325     */
1326    public String getRevision() {
1327      return RevisionUtils.extract("$Revision: 5953 $");
1328    }
1329  }
1330 
1331  /**
1332   * default constructor, prints only to stdout
1333   */
1334  public Debug() {
1335    this(null);
1336  }
1337 
1338  /**
1339   * logs the output to the specified file (and stdout). Size is 1,000,000 bytes
1340   * and 1 file.
1341   *
1342   * @param filename    the name of the log
1343   */
1344  public Debug(String filename) {
1345    this(filename, 1000000, 1);
1346  }
1347 
1348  /**
1349   * logs the output
1350   *
1351   * @param filename    the name of the log
1352   * @param size        the size of the files in bytes
1353   * @param numFiles    the number of files for rotating
1354   */
1355  public Debug(String filename, int size, int numFiles) {
1356    super();
1357   
1358    m_Log = newLog(filename, size, numFiles);
1359  }
1360 
1361  /**
1362   * turns the string representing a level, e.g., "FINE" or "ALL" into
1363   * the corresponding level (case-insensitive). The default is ALL.
1364   *
1365   * @param level       the string to return a level for
1366   * @return            the corresponding level or the default
1367   */
1368  public static Level stringToLevel(String level) {
1369    return Log.stringToLevel(level);
1370  }
1371 
1372  /**
1373   * returns a new Log instance
1374   *
1375   * @param filename    the name of the log
1376   * @param size        the size of the files in bytes
1377   * @param numFiles    the number of files for rotating
1378   * @return            the log instance
1379   */
1380  public static Log newLog(String filename, int size, int numFiles) {
1381    return new Log(filename, size, numFiles);
1382  }
1383 
1384  /**
1385   * prints the given message with level INFO
1386   *
1387   * @param message     the message to print
1388   */
1389  public void log(String message) {
1390    log(INFO, message);
1391  }
1392 
1393  /**
1394   * prints the given message with the specified level and an empty sourceclass
1395   *
1396   * @param level       the level of logging
1397   * @param message     the message to print
1398   */
1399  public void log(Level level, String message) {
1400    log(level, "", message);
1401  }
1402 
1403  /**
1404   * prints the given message with the specified level
1405   *
1406   * @param level       the level of logging
1407   * @param sourceclass the class that logs the message
1408   * @param message     the message to print
1409   */
1410  public void log(Level level, String sourceclass, String message) {
1411    log(level, sourceclass, "", message);
1412  }
1413 
1414  /**
1415   * prints the given message with the specified level
1416   *
1417   * @param level               the level of logging
1418   * @param sourceclass         the class that logs the message
1419   * @param sourcemethod        the method that logs the message
1420   * @param message             the message to print
1421   */
1422  public void log(Level level, String sourceclass, String sourcemethod, String message) {
1423    if (getEnabled())
1424      m_Log.log(level, sourceclass, sourcemethod, message);
1425  }
1426 
1427  /**
1428   * sets whether the logging is enabled or not
1429   *
1430   * @param value       if true logging will be enabled
1431   */
1432  public void setEnabled(boolean value) {
1433    m_Enabled = value;
1434  }
1435 
1436  /**
1437   * returns whether the logging is enabled
1438   *
1439   * @return            true if the logging is enabled
1440   */
1441  public boolean getEnabled() {
1442    return m_Enabled;
1443  }
1444 
1445  /**
1446   * returns a new instance of a clock
1447   *
1448   * @return            a new instance of a Clock
1449   */
1450  public static Clock newClock() {
1451    return new Clock();
1452  }
1453 
1454  /**
1455   * returns the instance of the Clock that is internally used
1456   *
1457   * @return            the clock that's being used
1458   */
1459  public Clock getClock() {
1460    return m_Clock;
1461  }
1462 
1463  /**
1464   * starts the clock
1465   */
1466  public void startClock() {
1467    m_Clock.start();
1468  }
1469 
1470  /**
1471   * stops the clock and prints the message associated with the time, but only
1472   * if the logging is enabled.
1473   *
1474   * @param message     the message to print
1475   * @see               #getEnabled()
1476   */
1477  public void stopClock(String message) {
1478    log(message + ": " + m_Clock);
1479  }
1480 
1481  /**
1482   * returns a default debug random object, with no particular seed and
1483   * debugging enabled.
1484   *
1485   * @return            a new instance of a Random object
1486   */
1487  public static java.util.Random newRandom() {
1488    return new Random(true);
1489  }
1490 
1491  /**
1492   * returns a debug random object with the specified seed and debugging
1493   * enabled.
1494   *
1495   * @param seed        the seed value
1496   * @return            a new instance of a Random object
1497   */
1498  public static java.util.Random newRandom(int seed) {
1499    return new Random(seed, true);
1500  }
1501
1502  /**
1503   * returns a default timestamp for the current date/time
1504   *
1505   * @return            a new timestamp
1506   */
1507  public static Timestamp newTimestamp() {
1508    return new Timestamp();
1509  }
1510 
1511  /**
1512   * returns the system temp directory
1513   *
1514   * @return            the temp directory
1515   */
1516  public static String getTempDir() {
1517    return System.getProperty("java.io.tmpdir");
1518  }
1519 
1520  /**
1521   * returns the home directory of the user
1522   *
1523   * @return            the user's home directory
1524   */
1525  public static String getHomeDir() {
1526    return System.getProperty("user.home");
1527  }
1528 
1529  /**
1530   * returns the current working directory of the user
1531   *
1532   * @return            the user's current working directory
1533   */
1534  public static String getCurrentDir() {
1535    return System.getProperty("user.dir");
1536  }
1537 
1538  /**
1539   * Writes the given object to the specified file. The string representation
1540   * of the object is appended to the file.
1541   *
1542   * @param filename    the file to write to
1543   * @param obj         the object to write to the file
1544   * @return            true if writing was successful
1545   */
1546  public static boolean writeToFile(String filename, Object obj) {
1547    return writeToFile(filename, obj, true);
1548  }
1549 
1550  /**
1551   * Writes the given message to the specified file. The message is appended
1552   * to the file.
1553   *
1554   * @param filename    the file to write to
1555   * @param message     the message to write
1556   * @return            true if writing was successful
1557   */
1558  public static boolean writeToFile(String filename, String message) {
1559    return writeToFile(filename, message, true);
1560  }
1561 
1562  /**
1563   * Writes the given object to the specified file. The string representation
1564   * of the object is either appended or replaces the current content of the
1565   * file.
1566   *
1567   * @param filename    the file to write to
1568   * @param obj         the object to write to the file
1569   * @param append      whether to append the message or not
1570   * @return            true if writing was successful
1571   */
1572  public static boolean writeToFile(String filename, Object obj, boolean append) {
1573    return writeToFile(filename, obj.toString(), append);
1574  }
1575 
1576  /**
1577   * Writes the given message to the specified file. The message is either
1578   * appended or replaces the current content of the file.
1579   *
1580   * @param filename    the file to write to
1581   * @param message     the message to write
1582   * @param append      whether to append the message or not
1583   * @return            true if writing was successful
1584   */
1585  public static boolean writeToFile(String filename, String message, boolean append) {
1586    boolean             result;
1587    BufferedWriter      writer;
1588   
1589    try {
1590      writer = new BufferedWriter(new FileWriter(filename, append));
1591      writer.write(message);
1592      writer.newLine();
1593      writer.flush();
1594      writer.close();
1595      result = true;
1596    }
1597    catch (Exception e) {
1598      result = false;
1599    }
1600   
1601    return result;
1602  }
1603 
1604  /**
1605   * writes the serialized object to the speicified file
1606   *
1607   * @param filename    the file to serialize the object to
1608   * @param o           the object to serialize
1609   * @return            true if writing was successful
1610   */
1611  public static boolean saveToFile(String filename, Object o) {
1612    boolean     result;
1613   
1614    if (SerializationHelper.isSerializable(o.getClass())) {
1615      try {
1616        SerializationHelper.write(filename, o);
1617        result = true;
1618      }
1619      catch (Exception e) {
1620        result = false;
1621      }
1622    }
1623    else {
1624      result = false;
1625    }
1626   
1627    return result;
1628  }
1629 
1630  /**
1631   * deserializes the content of the file and returns it, null if an error
1632   * occurred.
1633   *
1634   * @param filename    the name of the file to deserialize
1635   * @return            the deserialized content, null if problem occurred
1636   */
1637  public static Object loadFromFile(String filename) {
1638    Object      result;
1639   
1640    try {
1641      result = SerializationHelper.read(filename);
1642    }
1643    catch (Exception e) {
1644      result = null;
1645    }
1646   
1647    return result;
1648  }
1649 
1650  /**
1651   * Returns the revision string.
1652   *
1653   * @return            the revision
1654   */
1655  public String getRevision() {
1656    return RevisionUtils.extract("$Revision: 5953 $");
1657  }
1658}
Note: See TracBrowser for help on using the repository browser.