ToleratedDeltaMap.java

  1. /*
  2.  *
  3.  * The DbUnit Database Testing Framework
  4.  * Copyright (C)2002-2004, DbUnit.org
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2.1 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  *
  20.  */
  21. package org.dbunit.dataset.datatype;

  22. import java.math.BigDecimal;
  23. import java.util.Collections;
  24. import java.util.HashMap;
  25. import java.util.Map;

  26. import org.slf4j.Logger;
  27. import org.slf4j.LoggerFactory;

  28. /**
  29.  * Container that manages a map of {@link ToleratedDelta} objects to be used for
  30.  * numeric comparisons with an allowed deviation of two values
  31.  *
  32.  * @author gommma
  33.  * @author Last changed by: $Author$
  34.  * @version $Revision$ $Date$
  35.  * @since 2.3.0
  36.  */
  37. public class ToleratedDeltaMap
  38. {
  39.     /**
  40.      * List of {@link ToleratedDelta} objects
  41.      */
  42.     private Map _toleratedDeltas;
  43.     /**
  44.      * The logger
  45.      */
  46.     private Logger logger = LoggerFactory.getLogger(ToleratedDeltaMap.class);

  47.     /**
  48.      * Lookup a tolerated delta object by tableName and ColumnName.
  49.      *
  50.      * @param tableName
  51.      * @param columnName
  52.      * @return The object from the map or <code>null</code> if no such object
  53.      *         was found
  54.      */
  55.     public ToleratedDelta findToleratedDelta(String tableName,
  56.             String columnName)
  57.     {
  58.         Map toleratedDeltas = getToleratedDeltasNullSafe();
  59.         String mapKey = ToleratedDeltaMap.buildMapKey(tableName, columnName);
  60.         ToleratedDelta deltaObj = (ToleratedDelta) toleratedDeltas.get(mapKey);
  61.         return deltaObj;
  62.     }

  63.     private final Map getToleratedDeltasNullSafe()
  64.     {
  65.         Map res = getToleratedDeltas();
  66.         if (res == null)
  67.         {
  68.             return Collections.emptyMap();
  69.         }
  70.         return res;
  71.     }

  72.     public Map getToleratedDeltas()
  73.     {
  74.         return _toleratedDeltas;
  75.     }

  76.     /**
  77.      * Adds a new object to the map of tolerated deltas
  78.      *
  79.      * @param delta
  80.      *            The object to be added to the map
  81.      */
  82.     public void addToleratedDelta(ToleratedDelta delta)
  83.     {
  84.         if (delta == null)
  85.         {
  86.             throw new NullPointerException(
  87.                     "The parameter 'delta' must not be null");
  88.         }

  89.         if (this._toleratedDeltas == null)
  90.         {
  91.             this._toleratedDeltas = new HashMap();
  92.         }
  93.         String key = ToleratedDeltaMap.buildMapKey(delta);
  94.         // Put the new object into the map
  95.         ToleratedDelta removed =
  96.                 (ToleratedDelta) _toleratedDeltas.put(key, delta);
  97.         // Give a hint to the user when an already existing object has been
  98.         // overwritten/replaced
  99.         if (removed != null)
  100.         {
  101.             logger.debug(
  102.                     "Replaced old tolerated delta object from map with key {}. Old replaced object={}",
  103.                     key, removed);
  104.         }
  105.     }

  106.     /**
  107.      * Utility method to create a map key from the input parameters
  108.      *
  109.      * @param tableName
  110.      * @param columnName
  111.      * @return The key for the tolerated delta object map, consisting of the
  112.      *         tableName and the columnName
  113.      */
  114.     static String buildMapKey(String tableName, String columnName)
  115.     {
  116.         return tableName + "." + columnName;
  117.     }

  118.     /**
  119.      * Utility method to create a map key from the input parameters
  120.      *
  121.      * @param delta
  122.      * @return The key for the tolerated delta object map, consisting of the
  123.      *         tableName and the columnName
  124.      */
  125.     static String buildMapKey(ToleratedDelta delta)
  126.     {
  127.         return buildMapKey(delta.getTableName(), delta.getColumnName());
  128.     }

  129.     /**
  130.      * Simple bean that holds the tolerance for floating point comparisons for a
  131.      * specific database column.
  132.      */
  133.     public static class ToleratedDelta
  134.     {
  135.         private String tableName;
  136.         private String columnName;
  137.         private Precision toleratedDelta;

  138.         /**
  139.          * @param tableName
  140.          *            The name of the table
  141.          * @param columnName
  142.          *            The name of the column for which the tolerated delta
  143.          *            should be applied
  144.          * @param toleratedDelta
  145.          *            The tolerated delta. For example 1E-5 means that the
  146.          *            comparison must match the first 5 decimal digits. All
  147.          *            subsequent decimals are ignored.
  148.          */
  149.         public ToleratedDelta(String tableName, String columnName,
  150.                 double toleratedDelta)
  151.         {
  152.             this(tableName, columnName, new Precision(
  153.                     new BigDecimal(String.valueOf(toleratedDelta))));
  154.         }

  155.         /**
  156.          * @param tableName
  157.          *            The name of the table
  158.          * @param columnName
  159.          *            The name of the column for which the tolerated delta
  160.          *            should be applied
  161.          * @param toleratedDelta
  162.          *            The tolerated delta. For example 1E-5 means that the
  163.          *            comparison must match the first 5 decimal digits. All
  164.          *            subsequent decimals are ignored.
  165.          */
  166.         public ToleratedDelta(String tableName, String columnName,
  167.                 BigDecimal toleratedDelta)
  168.         {
  169.             this(tableName, columnName, new Precision(toleratedDelta));
  170.         }

  171.         /**
  172.          * @param tableName
  173.          *            The name of the table
  174.          * @param columnName
  175.          *            The name of the column for which the tolerated delta
  176.          *            should be applied
  177.          * @param toleratedDelta
  178.          *            The tolerated delta. For example 1E-5 means that the
  179.          *            comparison must match the first 5 decimal digits. All
  180.          *            subsequent decimals are ignored.
  181.          * @param isPercentage
  182.          *            Whether or not the given toleratedDelta value is a
  183.          *            percentage. See {@link Precision} for more.
  184.          */
  185.         public ToleratedDelta(String tableName, String columnName,
  186.                 BigDecimal toleratedDelta, boolean isPercentage)
  187.         {
  188.             this(tableName, columnName,
  189.                     new Precision(toleratedDelta, isPercentage));
  190.         }

  191.         /**
  192.          * @param tableName
  193.          *            The name of the table
  194.          * @param columnName
  195.          *            The name of the column for which the tolerated delta
  196.          *            should be applied
  197.          * @param toleratedDelta
  198.          *            The tolerated delta. For example 1E-5 means that the
  199.          *            comparison must match the first 5 decimal digits. All
  200.          *            subsequent decimals are ignored.
  201.          */
  202.         public ToleratedDelta(String tableName, String columnName,
  203.                 Precision toleratedDelta)
  204.         {
  205.             super();
  206.             this.tableName = tableName;
  207.             this.columnName = columnName;
  208.             this.toleratedDelta = toleratedDelta;
  209.         }

  210.         public String getTableName()
  211.         {
  212.             return tableName;
  213.         }

  214.         public String getColumnName()
  215.         {
  216.             return columnName;
  217.         }

  218.         public Precision getToleratedDelta()
  219.         {
  220.             return toleratedDelta;
  221.         }

  222.         /**
  223.          * Checks whether or not the <code>tableName</code> and the
  224.          * <code>columnName</code> match the ones of this object.
  225.          *
  226.          * @param tableName
  227.          * @param columnName
  228.          * @return <code>true</code> if both given values match those of this
  229.          *         object.
  230.          */
  231.         public boolean matches(String tableName, String columnName)
  232.         {
  233.             if (this.tableName.equals(tableName)
  234.                     && this.columnName.equals(columnName))
  235.             {
  236.                 return true;
  237.             } else
  238.             {
  239.                 return false;
  240.             }
  241.         }

  242.         public String toString()
  243.         {
  244.             final StringBuilder sb = new StringBuilder();
  245.             sb.append("tableName=").append(tableName);
  246.             sb.append(", columnName=").append(columnName);
  247.             sb.append(", toleratedDelta=").append(toleratedDelta);
  248.             return sb.toString();
  249.         }
  250.     }

  251.     /**
  252.      * Container for the tolerated delta of two values that are compared to each
  253.      * other.
  254.      *
  255.      * @author gommma (gommma AT users.sourceforge.net)
  256.      * @author Last changed by: $Author$
  257.      * @version $Revision$ $Date$
  258.      * @since 2.4.0
  259.      */
  260.     public static class Precision
  261.     {
  262.         private static final BigDecimal ZERO = new BigDecimal("0.0");

  263.         private final boolean percentage;
  264.         private final BigDecimal delta;

  265.         /**
  266.          * @param delta
  267.          *            The allowed/tolerated difference
  268.          */
  269.         public Precision(BigDecimal delta)
  270.         {
  271.             this(delta, false);
  272.         }

  273.         /**
  274.          * @param delta
  275.          *            The allowed/tolerated difference
  276.          * @param percentage
  277.          *            Whether or not the given <code>delta</code> should be
  278.          *            interpreted as percentage or not during the comparison
  279.          */
  280.         public Precision(BigDecimal delta, boolean percentage)
  281.         {
  282.             super();

  283.             if (delta.compareTo(ZERO) < 0)
  284.             {
  285.                 throw new IllegalArgumentException(
  286.                         "The given delta '" + delta + "' must be >= 0");
  287.             }

  288.             this.delta = delta;
  289.             this.percentage = percentage;
  290.         }

  291.         public boolean isPercentage()
  292.         {
  293.             return percentage;
  294.         }

  295.         public BigDecimal getDelta()
  296.         {
  297.             return delta;
  298.         }

  299.     }

  300. }