rel #6086 Improve rounding for progress monitor
authorAndreas Müller <a.mueller@bgbm.org>
Thu, 15 Sep 2016 12:27:43 +0000 (14:27 +0200)
committerAndreas Müller <a.mueller@bgbm.org>
Thu, 15 Sep 2016 12:27:43 +0000 (14:27 +0200)
 * fix error in rounding by using round not ceil
 * add method for user defined scaled rounding

cdmlib-commons/src/main/java/eu/etaxonomy/cdm/common/monitor/DefaultProgressMonitor.java
cdmlib-commons/src/test/java/eu/etaxonomy/cdm/common/monitor/DefaultProgressMonitorTest.java [new file with mode: 0644]

index d244ba83a7e19de08ae87c50936a63505d3a12c2..c64a549a7311671a56a07f7e047fe443639c3dee 100644 (file)
@@ -10,6 +10,7 @@
 package eu.etaxonomy.cdm.common.monitor;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
@@ -50,10 +51,6 @@ public class DefaultProgressMonitor implements IProgressMonitor {
 
     }
 
-
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#beginTask(java.lang.String, int)
-     */
     @Override
     public void beginTask(String taskName, int totalWork) {
         logger.info("Start " + taskName);
@@ -61,50 +58,32 @@ public class DefaultProgressMonitor implements IProgressMonitor {
         this.totalWork = totalWork;
     }
 
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#done()
-     */
     @Override
     public void done() {
         logger.info(taskName + "...Done");
     }
 
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#isCanceled()
-     */
     @Override
     public boolean isCanceled() {
         return isCanceled;
     }
 
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#setCanceled(boolean)
-     */
     @Override
     public void setCanceled(boolean isCanceled) {
         this.isCanceled = isCanceled;
     }
 
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#setTaskName(java.lang.String)
-     */
     @Override
     public void setTaskName(String taskName) {
         this.taskName = taskName;
     }
 
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#subTask(java.lang.String)
-     */
     @Override
     public void subTask(String subTask) {
         this.subTask = subTask;
         logger.info(/*getPercentage() + "% done." + */  " Next Task: " + subTask);
     }
 
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#worked(int)
-     */
     @Override
     public void worked(int work) {
         computeWorked(work);
@@ -120,33 +99,44 @@ public class DefaultProgressMonitor implements IProgressMonitor {
 
     private void computeWorked(double work){
         this.workDone = this.workDone +  work;
-        logger.info(getPercentage() + "% done (Completed Task: " + subTask + ")");
+        if (logger.isInfoEnabled()){ logger.info(getPercentage() + "% done (Completed Task: " + subTask + ")");}
     }
 
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#warning(java.lang.String)
-     */
     @Override
     public void warning(String warning) {
         logger.warn(warning);
     }
 
-    /* (non-Javadoc)
-     * @see eu.etaxonomy.cdm.common.IProgressMonitor#warning(java.lang.String, java.lang.Exception)
-     */
     @Override
     public void warning(String warning, Throwable exception) {
         logger.warn(warning);
         exception.printStackTrace();
     }
 
+    /**
+     * Percentage of work done. With all work done = 100.0d.
+     * As rounding errors may occur especially when using
+     * {@link SubProgressMonitor} the result is rounded to 5 digits.
+     * So do not use the result for additive percentages.
+     */
     public Double getPercentage(){
         if(totalWork == 0 ){
             return null;
         }
 
         double result = this.workDone * 100 / this.totalWork ;
-        result = Math.ceil((result * 100.0)) / 100.0;
+        //as double may have rounding errors especially when using subprogressmonitors
+        //we do round the result slightly
+        result = Math.round((result * 100000.0)) / 100000.0;
+        return result;
+    }
+
+    public BigDecimal getPercentageRounded(int scale){
+        if(totalWork == 0 ){
+            return null;
+        }
+        double percentage = this.workDone * 100 / this.totalWork ;
+        BigDecimal result = new BigDecimal(percentage).setScale( scale, BigDecimal.ROUND_HALF_UP );
         return result;
     }
 
diff --git a/cdmlib-commons/src/test/java/eu/etaxonomy/cdm/common/monitor/DefaultProgressMonitorTest.java b/cdmlib-commons/src/test/java/eu/etaxonomy/cdm/common/monitor/DefaultProgressMonitorTest.java
new file mode 100644 (file)
index 0000000..b97ba95
--- /dev/null
@@ -0,0 +1,70 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.common.monitor;
+
+import org.junit.Test;
+
+/**
+ * @author a.mueller
+ * @date 15.09.2016
+ *
+ */
+public class DefaultProgressMonitorTest {
+
+    int steps = 739893;
+
+    @Test
+    public void testRoundingWithoutSubProgressMonitor() {
+        DefaultProgressMonitor monitor = new DefaultProgressMonitor();
+        int subTaskTicks = 3273;
+
+        int subTasks = 130;
+        monitor.beginTask("Hallo", steps);
+        for (int i = 0; i<steps; i++){
+            monitor.worked(1);
+//            System.out.println(monitor.getPercentage());
+        }
+
+        monitor.done();
+        System.out.println(monitor.getPercentage());
+        System.out.println(monitor.getPercentageRounded(3));
+    }
+
+    @Test
+    public void testRoundingWithSubProgressMonitor() {
+        DefaultProgressMonitor monitor = new DefaultProgressMonitor();
+        int subTaskTicks = 3273;
+
+        int subTasks = 130;
+        monitor.beginTask("Hallo", steps);
+        for (int i = 0; i<steps-(subTaskTicks*subTasks); i++){
+            monitor.worked(1);
+//            System.out.println(monitor.getPercentage());
+        }
+
+        for (int i = 0; i < subTasks; i++){
+            SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, subTaskTicks);
+            int subTicks = 2457;
+            subMonitor.beginTask("SubMonitor", subTicks);
+            monitor.beginTask("Hallo", steps);
+            for (int j = 0; j < subTicks; j++){
+                subMonitor.worked(1);
+//            System.out.println(monitor.getPercentage());
+            }
+        }
+
+        monitor.done();
+        System.out.println(monitor.getPercentage());
+        System.out.println(monitor.getPercentageRounded(3));
+    }
+
+
+
+}