/*
* Copyright 2014 - LAit SpA
*				 Realizzato da Icona Management srl su commessa LAit SpA
* Copyright 2015- LAit SpA
*                                                  Aggiornato da LAit SpA
*
* Concesso in licenza a norma dell'EUPL, versione 1.1 o
* successive dell'EUPL (la "Licenza")– non appena saranno
* approvate dalla Commissione europea;
* Non è possibile utilizzare l'opera salvo nel rispetto della Licenza.
* È possibile ottenere una copia della Licenza al seguente indirizzo:
*
* http://ec.europa.eu/idabc/eupl
*
* Salvo diversamente indicato dalla legge applicabile o
* concordato per iscritto, il software distribuito secondo
* i termini della Licenza è distribuito "TAL QUALE",
* SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO,
* esplicite o implicite.
* Si veda la Licenza per la lingua specifica che disciplina
* le autorizzazioni e le limitazioni secondo i termini della
* Licenza.
*/
/**
 * 
 */
package it.laitspa.xsd.remover;

import it.laitspa.cpf.util.log.LogUtils;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Iterator;
import java.util.List;

/**
 * @author andrea
 * 
 */
public class FieldRemover<K, T>
{
  Class<K> packageName;
  Class<T> checkClass;

  public FieldRemover(Class<K> packageName, Class<T> checkClass)
  {
    this.packageName = packageName;
    this.checkClass = checkClass;
  }

  public void removeEmptyFields(Object obj)
  {
    try
    {
      if(obj == null)
        return;

      Class<?> c = obj.getClass();
      LogUtils.info(getClass(), "Checking class " + c.getName());

      Method[] allMethods = c.getDeclaredMethods();

      for(Method m : allMethods)
      {
        if(!m.getName().startsWith("get"))
          continue;

        Class<?> r_class = m.getReturnType();

        if(r_class == checkClass)
        {
          // Check result.
          //
          @SuppressWarnings("unchecked")
          T res =  (T) m.invoke(obj, (Object[])null);
          if (res == null)
            continue;
          
          String lv = res.toString();
          
          if(lv != null && lv.trim().length() == 0)
          {
            LogUtils.info(getClass(), "Converting empty string for method "
                + m.getName() + " inside class " + c.getName());
            String s_method = m.getName().replace("get", "set");
            Method s_m = c.getMethod(s_method, new Class<?>[] { checkClass });
            s_m.invoke(obj, new Object[] { null });
            LogUtils.info(getClass(), "Converted empty string for method "
                + s_m.getName() + " inside class " + c.getName() + " into null.");
          }
        }
        else
        {
          Package pk = r_class.getPackage();
          
          // Check for primitive types
          //
          if (pk == null)
            continue;
          
          if(pk.getName().contains(packageName.getPackage().getName()))
          {
            Object lv = (Object)m.invoke(obj, (Object[])null);
            removeEmptyFields(lv);
          }
          else if(List.class.isAssignableFrom(r_class))
          {
            // get the type as generic
            //
            ParameterizedType fieldGenericType = (ParameterizedType)m.getGenericReturnType();

            // get it's first type parameter
            //
            Class<?> fieldTypeParameterType =
                (Class<?>)fieldGenericType.getActualTypeArguments()[0];

            pk = fieldTypeParameterType.getPackage();

            if(pk.getName().contains(packageName.getPackage().getName()))
            {
              List<?> lv = (List<?>) m.invoke(obj, (Object[])null);
              Iterator<?> i_lv = lv.iterator();
              while (i_lv.hasNext())
                removeEmptyFields(i_lv.next());
            }
          }
        }
      }

    }
    catch(Exception e)
    {
      LogUtils.error(getClass(), "Error while removing fields.", e);
    }
  }

}
