MatchMetrics.java

/*
** Module   : MemberMetrics.java
** Abstract : container for metrics state related to the usage of a given class member
**
** Copyright (c) 2021-2023, Golden Code Development Corporation.
**
** -#- -I- --Date-- --------------------------------------Description---------------------------------------
** 001 GES 20210408 First version.
** 002 CA  20230928 Refactored the fuzzy method resolution to be used by runtime, too. 
*/

/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.uast;

/**
 * Stores metrics state related to the usage of a given class member.  This state cannot be stored in the
 * member data itself, since it is different at every usage location of the given member.  
 */
public class MatchMetrics
implements Comparable<MatchMetrics>
{
   /** The member to which the metrics refer. */
   MethodData data;
   
   /** Number of exact matches. */
   int exact = 0;
   
   /** Number of matches due to widening or narrowing conversion. */
   int cvt = 0;
   
   /** Number of exact extent matches (none to none, fixed to fixed, indeterminate to indeterminate). */
   int extExact = 0;
   
   /** Number of matches due to fixed extent to indeterminate conversion. */
   int extCvt = 0;
   
   /** Number of wildcard matches. */
   int wildcard = 0;
   
   /** Number of OO inheritance levels the caller type is from the callee type. */
   int[] ooLvl;
   
   /** Type overrides needed due to fuzzy matching. */
   String[] overrides;
   
   /**
    * Construct an instance which references the given member.
    * 
    * @param    data
    *           The member being referenced.
    */
   public MatchMetrics(MethodData data)
   {
      this.data      = data;
      this.ooLvl     = new int[data.getSignature().length];
      this.overrides = new String[data.getSignature().length];
   }
   
   /**
    * Compares this object with the given other object to calculate a relative ordering between the two
    * instances.
    * 
    * @param    other
    *           The other instance.  Must NOT be {@code null}.
    *           
    * @return   -1, 0 or 1 if this instance is less than, equal to, or greater than the other object.
    * 
    * @throws   NullPointerException
    *           If the parameter is {@code null}.
    */
   public int compareTo(MatchMetrics other)
   {
      int diffExact  = exact - other.exact;
      int diffCvt    = cvt - other.cvt;
      int diffExt    = extExact - other.extExact;
      int diffExtCvt = extCvt - other.extCvt;
      
      if (diffExact == 0 && diffCvt == 0 && diffExt == 0 && diffExtCvt == 0)
      {
         return compareInheritanceLevels(other);
      }
      else if (diffExact > 0 ||
               (diffExact == 0 && diffCvt > 0) ||
               (diffExact == 0 && diffCvt == 0 && diffExt > 0) ||
               (diffExact == 0 && diffCvt == 0 && diffExt == 0 && diffExtCvt > 0))
      {
         return 1;
      }
      else
      {
         return -1;
      }
   }
   
   /**
    * Report if the two instances have equivalent state.
    * 
    * @param    other
    *           The other instance to check against.
    *          
    * @return   {@code true} if the other instance is non-null, is the same class and the state is equivalent
    *           as reported by {@link #compareTo}.  {@code false} otherwise.
    */
   public boolean equals(Object other)
   {
      if (other == null || !(other instanceof MatchMetrics))
      {
         return false;
      }
      
      return compareTo((MatchMetrics) other) == 0;
   }

   /**
    * Render the state of the instance in a text form.
    *
    * @return   The rendered instance.
    */
   public String toString()
   {
      return String.format("METRICS %d exact; %d cvt; %d extExact; %d extCvt; %d wildcard; " +
                           "%s ooLvl; %s overrides; \n        %s data",
                           exact,
                           cvt,
                           extExact,
                           extCvt,
                           wildcard,
                           ooLvl,
                           overrides,
                           data);       
   }
   
   /**
    * Compares this object with the given other object to calculate if one of them matched based on OO
    * inheritance and is "closer" in its relationship.  The first OO level that is different will
    * determine the outcome unless no OO levels are different in which case the instances are equivalent.
    * 
    * @param    other
    *           The other instance.  Must NOT be {@code null}.
    *           
    * @return   -1, 0 or 1 if this instance is less than (farther than), equal to, or greater than (closer
    *           than) the other object.
    * 
    * @throws   NullPointerException
    *           If the parameter is {@code null}.
    */
   private int compareInheritanceLevels(MatchMetrics other)
   {
      for (int i = 0; i < ooLvl.length; i++)
      {
         int diff = ooLvl[i] - other.ooLvl[i];
         
         if (diff > 0)
         {
            // farther away than other
            return -1;
         }
         else if (diff < 0)
         {
            // closer than other
            return 1;
         }
      }
      
      // no difference across the entire array
      return 0;
   }
}