All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.classloading.spi.version.VersionComparatorRegistry Maven / Gradle / Ivy

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.classloading.spi.version;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Version comparator registry.
 *
 * @author Ales Justin
 * @author Adrian Brock
 */
public class VersionComparatorRegistry
{
   /** The singleton */
   private static VersionComparatorRegistry registry = new VersionComparatorRegistry();

   /** The comparators */
   private Map, Map, VersionComparator>> comparatorMap = new ConcurrentHashMap, Map, VersionComparator>>();

   /**
    * Create a new VersionComparatorRegistry.
    */
   public VersionComparatorRegistry()
   {
      // register all our known impls
      internalRegisterVersionComparator(Version.class, Version.class, new VersionToVersionComparator(), true);
      internalRegisterVersionComparator(Version.class, String.class, new VersionToStringComparator(), true);
      internalRegisterVersionComparator(String.class, String.class, new StringToStringComparator(), true);
   }

   /**
    * Get the singleton
    *  
    * @return the singleton
    */
   public static VersionComparatorRegistry getInstance()
   {
      return registry;
   }

   /**
    * Remove the version comparator.
    *
    * @param  the first version type
    * @param  the second version type
    * @param t first version impl
    * @param u second version impl
    */
   public  void removeVersionComparator(Class t, Class u)
   {
      registerVersionComparator(t, u, null);
   }

   /**
    * Remove the version comparator.
    *
    * @param  the version type
    * @param t version impl
    */
   public  void removeVersionComparator(Class t)
   {
      registerVersionComparator(t, null);
   }

   /**
    * Register version comparator.
    * If comparator parameter is null, it's actually a removal.
    *
    * @param  the version type
    * @param t version impl
    * @param comparator the version comparator
    */
   public  void registerVersionComparator(Class t, VersionComparator comparator)
   {
      registerVersionComparator(t, t, comparator);
   }

   /**
    * Register version comparator.
    * If comparator parameter is null, it's actually a removal.
    *
    * @param  the first version type
    * @param  the second version type
    * @param t first version impl
    * @param u second version impl
    * @param comparator the version comparator
    */
   public  void registerVersionComparator(Class t, Class u, VersionComparator comparator)
   {
      internalRegisterVersionComparator(t, u, comparator, false);
   }

   /**
    * Register version comparator.
    * If comparator parameter is null, it's actually a removal.
    *
    * @param  the first version type
    * @param  the second version type
    * @param t first version impl
    * @param u second version impl
    * @param comparator the version comparator
    * @param setup whether this is during setup
    */
   private  void internalRegisterVersionComparator(Class t, Class u, VersionComparator comparator, boolean setup)
   {
      if (t == null || u == null)
         throw new IllegalArgumentException("Null version class");

      // Don't allow removal of the standard comparators
      if (setup == false)
      {
         if (t == Version.class && u == Version.class)
            throw new IllegalArgumentException("You can't remove or replace the built in Version->Version comparator");
         if (t == Version.class && u == String.class)
            throw new IllegalArgumentException("You can't remove or replace the built in Version->String comparator");
         if (t == String.class && u == Version.class)
            throw new IllegalArgumentException("You can't remove or replace the built in Version->String comparator");
         if (t == String.class && u == String.class)
            throw new IllegalArgumentException("You can't remove or replace the built in Version->String comparator");
      }
      
      if (comparator == null)
      {
         Map, VersionComparator> tKeyMap = comparatorMap.get(t);
         if (tKeyMap != null)
            tKeyMap.remove(u);

         // different impls
         if (t.equals(u) == false)
         {
            Map, VersionComparator> uKeyMap = comparatorMap.get(u);
            if (uKeyMap != null)
               uKeyMap.remove(t);
         }
      }
      else
      {
         Map, VersionComparator> tKeyMap = comparatorMap.get(t);
         if (tKeyMap == null)
         {
            tKeyMap = new ConcurrentHashMap, VersionComparator>();
            comparatorMap.put(t, tKeyMap);
         }
         tKeyMap.put(u, comparator);

         // different impls
         if (t.equals(u) == false)
         {
            Map, VersionComparator> uKeyMap = comparatorMap.get(u);
            if (uKeyMap == null)
            {
               uKeyMap = new ConcurrentHashMap, VersionComparator>();
               comparatorMap.put(u, uKeyMap);
            }
            uKeyMap.put(t, new SwitchVersionComparator(comparator));
         }
      }
   }

   /**
    * Get the comparator.
    *
    * @param  the first version type
    * @param  the second version type
    * @param t first version impl
    * @param u second version impl 
    * @return the matching comparator
    */
   @SuppressWarnings("unchecked")
   protected  VersionComparator getComparator(T t, U u)
   {
      if (t == null || u == null)
         return null;
      Class classT = (Class) t.getClass();
      Class classU = (Class) u.getClass();
      return getComparator(classT, classU);
   }

   /**
    * Get the comparator.
    *
    * @param  the first version type
    * @param  the second version type
    * @param t first version impl class
    * @param u second version impl class
    * @return the matching comparator
    */
   @SuppressWarnings("unchecked")
   public  VersionComparator getComparator(Class t, Class u)
   {
      Map, VersionComparator> map = comparatorMap.get(t);
      if (map == null)
         return null;
      else
         return (VersionComparator) map.get(u);
   }

   /**
    * Compare two version impls.
    *
    * @param  the first version type
    * @param  the second version type
    * @param t the first version
    * @param u the second version
    * @return the compare result
    */
   public  int compare(T t, U u)
   {
      VersionComparator comparator = getComparator(t, u);
      if (comparator == null)
      {
         String classT = null;
         if (t != null)
            classT = t.getClass().getName();
         String classU = null;
         if (u != null)
            classU = u.getClass().getName();
         throw new IllegalArgumentException("Missing version comparator for Version pair: (" + classT + "," + classU + ")");
      }

      return comparator.compare(t, u);
   }

   /**
    * Test whether two version impls are request.
    *
    * @param  the first version type
    * @param  the second version type
    * @param t T version impl
    * @param u U version impl
    * @return the compare result
    */
   public  boolean same(T t, U u)
   {
      VersionComparator comparator = getComparator(t, u);
      if (comparator == null)
         return false;

      return comparator.compare(t, u) == 0;
   }

   /**
    * Switch the compare value.
    *
    * @param  the first version type
    * @param  the second version type
    */
   private static class SwitchVersionComparator implements VersionComparator
   {
      /** The delegate */
      private VersionComparator delegate;

      /**
       * Create a new SwitchVersionComparator.
       * 
       * @param delegate the delegate comparator
       */
      public SwitchVersionComparator(VersionComparator delegate)
      {
         if (delegate == null)
            throw new IllegalArgumentException("Null delegate");
         this.delegate = delegate;
      }

      public int compare(T t, U u)
      {
         return (-1) * delegate.compare(u, t); 
      }
   }

   /**
    * VersionToVersionComparator.
    */
   private static class VersionToVersionComparator implements VersionComparator
   {
      public int compare(Version t, Version u)
      {
         return t.compareTo(u);
      }
   }

   /**
    * VersionToStringComparator.
    */
   private static class VersionToStringComparator implements VersionComparator
   {
      public int compare(Version t, String u)
      {
         return t.compareTo(Version.parseVersion(u));
      }
   }

   /**
    * StringToStringComparator.
    */
   private static class StringToStringComparator implements VersionComparator
   {
      public int compare(String t, String u)
      {
         return Version.parseVersion(t).compareTo(Version.parseVersion(u));
      }
   }
}