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

net.alantea.viewml.VmlUtils Maven / Gradle / Ivy

package net.alantea.viewml;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import net.alantea.liteprops.Property;
import net.alantea.utils.MultiMessages;
import net.alantea.viewml.handlers.ModelHandler;
import net.alantea.viewml.internal.ActionsLoader;
import net.alantea.viewml.internal.ModelsLoader;
import net.alantea.viewml.internal.Referencer;


/**
 * The Class TxmlUtils.
 */
public final class VmlUtils
{
   
   /**
    * The Enum DIRECTION.
    */
   public static enum LinkDirection 
   { 
      /** The To. */
      To, 
      /** The From. */
      From,
      /** The Both. */
      Both
   }

   /**
    * Instantiates a new txml utils.
    */
   private VmlUtils()
   {
   }

   
   /**
    * Do binding.
    *
    * @param parser the parser
    * @param sourceClass the source class
    * @param sourcePropertyName the source property name
    * @param targetObject the target object
    * @param targetClassName the target class name
    * @param targetPropertyName the target property name
    * @param direction the direction
    * @throws VmlException the TXML exception
    */
   public static void doClassBinding(VmlParser parser, String sourceClass, String sourcePropertyName, Object targetObject, 
         String targetClassName, String targetPropertyName, LinkDirection direction) throws VmlException
   {
      Class cl;
      try
      {
         cl = VmlUtils.class.getClassLoader().loadClass(sourceClass);
         Property sourceProperty = getProperty(null, sourcePropertyName, cl);
         doInternalBinding(parser, sourceProperty, sourcePropertyName, targetObject, 
               targetClassName, targetPropertyName, direction);
      }
      catch (ClassNotFoundException e)
      {
         throw new VmlException(MultiMessages.get("VmlException.binding.unable", sourcePropertyName, 
               sourceClass, direction.name(), targetPropertyName, targetClassName));
      }
   }

   
   /**
    * Do listen.
    *
    * @param parser the parser
    * @param sourceObject the source object
    * @param sourcePropertyName the source property name
    * @param action the action
    * @throws VmlException the TXML exception
    */
   public static void doListen(VmlParser parser, Object sourceObject, String sourcePropertyName, String action) throws VmlException
   {
      Property sourceProperty = getProperty(sourceObject, sourcePropertyName, sourceObject.getClass());
      VmlAction listener = ActionsLoader.getAction(action);
      if (listener != null)
      {
         sourceProperty.addListener((o, n) -> listener.invoke());
      }
   }

   
   /**
    * Do binding.
    *
    * @param parser the parser
    * @param sourceObject the source object
    * @param sourcePropertyName the source property name
    * @param targetObject the target object
    * @param targetClassName the target class name
    * @param targetPropertyName the target property name
    * @param direction the direction
    * @throws VmlException the TXML exception
    */
   public static void doBinding(VmlParser parser, Object sourceObject, String sourcePropertyName, Object targetObject, 
         String targetClassName, String targetPropertyName, LinkDirection direction) throws VmlException
   {
      Property sourceProperty = getProperty(sourceObject, sourcePropertyName, sourceObject.getClass());
      doInternalBinding(parser, sourceProperty, sourcePropertyName, targetObject, 
          targetClassName, targetPropertyName, direction);
   }

   
   /**
    * Do binding.
    *
    * @param parser the parser
    * @param sourceProperty the source property
    * @param sourcePropertyName the source property name
    * @param targetObject the target object
    * @param targetClassName the target class name
    * @param targetPropertyName the target property name
    * @param direction the direction
    * @throws VmlException the TXML exception
    */
   private static void doInternalBinding(VmlParser parser, Property sourceProperty, String sourcePropertyName, Object targetObject, 
         String targetClassName, String targetPropertyName, LinkDirection direction) throws VmlException
   {
      boolean done = false;
      String targetClName = targetClassName;
      Property targetProperty = null;
      
      if (targetObject != null)
      {
         if (targetObject instanceof ModelHandler)
         {
            targetProperty = ((ModelHandler)targetObject).getProperty(targetPropertyName);
         }
         else
         {
            targetProperty = VmlUtils.getProperty(targetObject, targetPropertyName, targetObject.getClass());
         }
         targetClName = targetObject.getClass().getName();
      }
      else if (targetClName != null)
      {
         try
         {
            Class realClass = VmlUtils.class.getClassLoader().loadClass(targetClassName);
            targetProperty = VmlUtils.getProperty(null, targetPropertyName, realClass);
         }
         catch (ClassNotFoundException e)
         {
            throw new VmlException(MultiMessages.get("TXMLException.binding.unable", sourcePropertyName, 
                  targetClassName, direction.name(), targetPropertyName, targetClassName));
         }
      }
      else if (targetPropertyName != null)
      {
         targetProperty = (Property) Referencer.getReference(targetPropertyName);
      }
      
      if ((targetProperty != null) && (sourceProperty != null))
      {
         done = doLink(sourceProperty, targetProperty, direction);
      }
      if (!done)
      {
         throw new VmlException(MultiMessages.get("TXMLException.binding.unable", sourcePropertyName, 
               direction.name(), targetPropertyName, targetClName));
      }
   }

   /**
    * Do link.
    *
    * @param sourceProperty the source property
    * @param targetProperty the target property
    * @param direction the direction
    * @return true, if successful
    */
   @SuppressWarnings({ "unchecked", "rawtypes" })
   public static boolean doLink(Property sourceProperty, Property targetProperty, LinkDirection direction)
   {
      boolean done = false;
      Object targetBean = targetProperty.get();
      Object sourceBean = targetProperty.get();
      boolean valid = (sourceBean == null) || (targetBean == null) || (sourceBean.getClass().isAssignableFrom(targetBean.getClass()));
      switch (direction)
      {
         case To :
            targetProperty.unbind();
            targetProperty.link(sourceProperty);
            done = true;
            break;

         case From :
            if (valid)
            {
               sourceProperty.unbind();
               sourceProperty.link(targetProperty);
               done = true;
            }
            break;

         case Both :
            if (valid)
            {
               sourceProperty.bind(targetProperty);
               done = true;
            }
            break;

         default :
            // nothing
      }
      return done;
   }
   
   /**
    * Gets the property.
    *
    * @param object the object
    * @param propertyName the property name
    * @return the property
    * @throws VmlException the TXML exception
    */
   public static Property getProperty(Object object, String propertyName) throws VmlException
   {
      if (object instanceof Class)
      {
         return getProperty(null, propertyName, (Class) object);
      }
      else
      {
         return getProperty(object, propertyName, object.getClass());
      }
   }
   
   /**
    * Gets the property.
    *
    * @param object the object
    * @param property the property name
    * @param theClass the class
    * @return the property
    * @throws VmlException the TXML exception
    */
   public static Property getProperty(Object object, String property, Class theClass) throws VmlException
   {
      if (object instanceof ModelHandler)
      {
         return ((ModelHandler) object).getProperty(property);
      }
      
      Class cl = theClass;
      Property prop = null;
      if (cl == null)
      {
         cl = object.getClass();
      }
      try
      {
         Field field = cl.getDeclaredField(property);
         field.setAccessible(true);
         prop = (Property) field.get(object);
      }
      catch (NoSuchFieldException e0)
      {
         try
         {
            Field field = cl.getDeclaredField(property + "Property");
            field.setAccessible(true);
            prop = (Property) field.get(object);
         }
         catch (NoSuchFieldException e)
         {
            if (!Object.class.equals(cl))
            {
               prop = getProperty(object, property, cl.getSuperclass());
               if (prop == null)
               {
                  for (Class c : cl.getInterfaces())
                  {
                     if (prop == null)
                     {
                        prop = getProperty(object, property, c);
                     }
                  }
               }
            }
         }
         catch (IllegalArgumentException | IllegalAccessException | SecurityException e)
         {
            // nothing
         }
      }
      catch (IllegalArgumentException | IllegalAccessException | SecurityException e)
      {
         // nothing
      }
      if (prop == null)
      {
         throw new VmlException(MultiMessages.get("TXMLException.find.property.unable", property, cl.getName()));
      }
      return prop;
   }
   
   /**
    * Gets the property from the model name.
    *
    * @param modelName the model name
    * @return the property
    * @throws VmlException the TXML exception
    */
   public static Property getProperty(String modelName) throws VmlException
   {
      String[] tokens = modelName.split("::");
      if (tokens.length == 2)
      {
         return getProperty(null, ModelsLoader.getModelClassName(tokens[0]), tokens[1]);
      }
      else
      {
         return null;
      }
   }
   
   /**
    * Gets the property from the class hierarchy.
    *
    * @param target the target
    * @param className the class name
    * @param propertyName the property name
    * @return the property
    * @throws VmlException the TXML exception
    */
   public static Property getProperty(Object target, String className, String propertyName) throws VmlException
   {
      return getProperty(target, className, propertyName, null);
   }
   
   /**
    * Gets the property from the class hierarchy.
    *
    * @param theTarget the the target
    * @param className the class name
    * @param propertyName the property name
    * @param baseClass the base class or null for initialization
    * @return the property
    * @throws VmlException the TXML exception
    */
   private static Property getProperty(Object theTarget, String className, String propertyName, Class baseClass) throws VmlException
   {
      Object target = theTarget;
      Class cl = baseClass;
      if ((cl == null) && (className != null))
      {
         Object ref = Referencer.getReference(className);
         if (ref == null)
         {
            try
            {
               cl = VmlUtils.class.getClassLoader().loadClass(className);
            }
            catch (ClassNotFoundException e)
            {
               return null;
            }
         }
         else
         {
            target = ref;
         }
      }
      
      Property prop = null;
      try
      {
         Field field = cl.getDeclaredField(propertyName);
         field.setAccessible(true);
         prop = (Property) field.get(target);
      }
      catch (NoSuchFieldException e)
      {
         if (!Object.class.equals(cl))
         {
            prop = getProperty(target, className, propertyName, cl.getSuperclass());
         }
      }
      catch (IllegalArgumentException | IllegalAccessException | SecurityException e)
      {
         // nothing;
      }
      if (prop == null)
      {
         throw new VmlException(MultiMessages.get("TXMLException.find.property.unable", propertyName, cl.getName()));
      }
      return prop;
   }
   
   /**
    * Gets the boolean value.
    *
    * @param value the value
    * @return the boolean value
    */
   public static boolean getBooleanValue(String value)
   {
      boolean ret = false;
      Property property = null;
      try
      {
         property = VmlUtils.getProperty(value);
      }
      catch (VmlException e)
      {
         return false;
      }
      if (property != null)
      {
         ret = getBooleanValue(property);
      }
         
      return ret;
   }
   
   /**
    * Gets the boolean value.
    *
    * @param property the property
    * @return the boolean value
    */
   public static boolean getBooleanValue(Property property)
   {
      boolean ret = false;
      if (property != null)
      {
         ret = VmlUtils.getBooleanValue(property);
      }
         
         return ret;
   }
   
   /**
    * Type value.
    *
    * @param method the method
    * @param valueText the value text
    * @return the object
    * @throws VmlException the vml exception
    */
   public static Object typeValue(Method method, String valueText) throws VmlException
   {
      Class targetClass = method.getParameterTypes()[method.getParameterCount() - 1];
      return typeValue(targetClass, valueText);
   }

   /**
    * Type value.
    *
    * @param targetClass the target class
    * @param valueText the value text
    * @return the object
    * @throws VmlException the TXML exception
    */
   public static Object typeValue(Class targetClass, String valueText) throws VmlException
   {
      Object value = null;
      if ((Boolean.class.equals(targetClass)) || (Boolean.TYPE.equals(targetClass)))
      {
         value = Boolean.parseBoolean(valueText);
      }
      else if ((Integer.class.equals(targetClass)) || (Integer.TYPE.equals(targetClass)))
      {
         value = Integer.parseInt(valueText);
      }
      else if ((Long.class.equals(targetClass)) || (Long.TYPE.equals(targetClass)))
      {
         value = Long.parseLong(valueText);
      }
      else if ((Float.class.equals(targetClass)) || (Float.TYPE.equals(targetClass)))
      {
         value = Float.parseFloat(valueText);
      }
      else
      {
         value = typeValue1(targetClass, valueText);
      }
      return value;
   }
      
   /**
    * Type value 1.
    *
    * @param targetClass the target class
    * @param valueText the value text
    * @return the object
    * @throws VmlException the TXML exception
    */
   private static Object typeValue1(Class targetClass, String valueText) throws VmlException
   {
      Object value = null;
      if ((Double.class.equals(targetClass)) || (Double.TYPE.equals(targetClass)))
      {
         value = Double.parseDouble(valueText);
      }
      else if (String.class.equals(targetClass))
      {
         value = MultiMessages.get(valueText);
      }
      else if ((Byte.class.equals(targetClass)) || (Byte.TYPE.equals(targetClass)))
      {
         value = Byte.decode(valueText);
      }
      else
      {
         value = typeValue2(targetClass, valueText);
      }
      return value;
   }
      
   /**
    * Type value 2.
    *
    * @param targetClass the target class
    * @param valueText the value text
    * @return the object
    * @throws VmlException the TXML exception
    */
   private static Object typeValue2(Class targetClass, String valueText) throws VmlException
   {
      Object value = null;
      if (targetClass.isEnum())
      {
         Method meth;
         try
         {
            meth = targetClass.getMethod("valueOf", String.class);
            meth.setAccessible(true);
            value = meth.invoke(null, valueText);
         }
         catch (NoSuchMethodException | SecurityException | IllegalAccessException
               | IllegalArgumentException | InvocationTargetException e)
         {
            throw new VmlException("can not convert value : " + valueText + " to " + targetClass.getName());
         }
      }
      else
      {
         Constructor con;
         try
         {
            con = targetClass.getConstructor(String.class);
            if (con != null)
            {
               value = con.newInstance(valueText);
            }
         }
         catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
               | IllegalArgumentException | InvocationTargetException e)
         {
            throw new VmlException("can not convert value : " + valueText + " to " + targetClass.getName());
         }
      }
      return value;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy