package it.micegroup.voila2.cartridge.library.javaservice;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;

/**
 * 
 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
 * @autohr Luca Barone <luca.barone@micegroup.it>
 * @author Fabio Memoli <fabio.memoli@micegroup.it>
 */
public class TypeUtils {
	// MODEL
	private static final String LONG = "Long";
	private static final String CODE = "Code";
	private static final String FLAG = "Flag";
	private static final String VALUE = "Value";
	private static final String NUMBER = "Number";
	private static final String STRING = "String";
	private static final String INTEGER = "Integer";
	private static final String BOOLEAN = "Boolean";
	private static final String DATE = "Date";
	private static final String DATETIME = "Datetime";
	private static final String CURRENCY = "Currency";
	private static final String BLOB = "Blob";
	private static final String LOB = "Lob";
	private static final String CLOB = "Clob";

	// JAVA
	private static final String DEFAULT_JAVATYPE_FOR_DATE = "Date";
	private static final String DEFAULT_JAVATYPE_FOR_DATETIME = "LocalDateTime";
	private static final String DEFAULT_JAVATYPE_FOR_NUMBER = "Integer";
	private static final String DEFAULT_JAVATYPE_FOR_CODE = "Integer";
	private static final String DEFAULT_JAVATYPE_FOR_VALUE = "BigDecimal";
	private static final String DEFAULT_JAVATYPE_FOR_CURRENCY = "BigDecimal";
	private static final String DEFAULT_JAVATYPE_FOR_STRING = "String";
	private static final String DEFAULT_JAVATYPE_FOR_BOOLEAN = "Boolean";
	private static final String DEFAULT_JAVATYPE_FOR_LONG = "Long";
	private static final String DEFAULT_JAVATYPE_FOR_BLOB = "byte[]";
	private static final String DEFAULT_JAVATYPE_FOR_LOB = "String";
	private static final String DEFAULT_JAVATYPE_FOR_CLOB = "String";

	// SQL
	private static final String DEFAULT_SQLTYPE_FOR_DATE = "DATE";
	private static final String DEFAULT_SQLTYPE_FOR_DATETIME = "DATETIME";
	private static final String DEFAULT_SQLTYPE_FOR_NUMBER = "INTEGER";
	private static final String DEFAULT_SQLTYPE_FOR_CODE = "INTEGER";
	private static final String DEFAULT_SQLTYPE_FOR_VALUE = "NUMERIC";
	private static final String DEFAULT_SQLTYPE_FOR_CURRENCY = "NUMERIC";
	private static final String DEFAULT_SQLTYPE_FOR_STRING = "VARCHAR";
	private static final String DEFAULT_SQLTYPE_FOR_BOOLEAN = "BOOLEAN";
	private static final String DEFAULT_SQLTYPE_FOR_LONG = "NUMBER";
	private static final String DEFAULT_SQLTYPE_FOR_BLOB = "BLOB";
	private static final String DEFAULT_SQLTYPE_FOR_LOB = "LONGTEXT";
	private static final String DEFAULT_SQLTYPE_FOR_CLOB = "LONGTEXT";

	// SQL
	private static final String DEFAULT_SQLLENGTH_FOR_DATETIME = "";
	private static final String DEFAULT_SQLLENGTH_FOR_DATE = "";
	private static final String DEFAULT_SQLLENGTH_FOR_NUMBER = "11";
	private static final String DEFAULT_SQLLENGTH_FOR_CODE = "";
	private static final String DEFAULT_SQLLENGTH_FOR_VALUE = "12,2";
	private static final String DEFAULT_SQLLENGTH_FOR_CURRENCY = "14,2";
	private static final String DEFAULT_SQLLENGTH_FOR_STRING = "80";
	private static final String DEFAULT_SQLLENGTH_FOR_BOOLEAN = "";
	private static final String DEFAULT_SQLLENGTH_FOR_LONG = "15";
	private static final String DEFAULT_SQLLENGTH_FOR_BLOB = "";
	private static final String DEFAULT_SQLLENGTH_FOR_LOB = "";
	private static final String DEFAULT_SQLLENGTH_FOR_CLOB = "";

	// ANGULAR
	private static final String DEFAULT_ANGULARTYPE_FOR_DATETIME = "Date";
	private static final String DEFAULT_ANGULARTYPE_FOR_DATE = "Date";
	private static final String DEFAULT_ANGULARTYPE_FOR_NUMBER = "number";
	private static final String DEFAULT_ANGULARTYPE_FOR_CODE = "number";
	private static final String DEFAULT_ANGULARTYPE_FOR_VALUE = "number";
	private static final String DEFAULT_ANGULARTYPE_FOR_CURRENCY = "number";
	private static final String DEFAULT_ANGULARTYPE_FOR_STRING = "string";
	private static final String DEFAULT_ANGULARTYPE_FOR_BOOLEAN = "boolean";
	private static final String DEFAULT_ANGULARTYPE_FOR_LONG = "number";

	// FILTER
	private static final String DEFAULT_FILTER_TYPE_FOR_DATETIME = "LocalDateTimeFilter";
	private static final String DEFAULT_FILTER_TYPE_FOR_DATE = "LocalDateFilter";
	private static final String DEFAULT_FILTER_TYPE_FOR_NUMBER = "IntegerFilter";
	private static final String DEFAULT_FILTER_TYPE_FOR_CODE = "IntegerFilter";
	private static final String DEFAULT_FILTER_TYPE_FOR_VALUE = "BigDecimalFilter";
	private static final String DEFAULT_FILTER_TYPE_FOR_CURRENCY = "BigDecimalFilter";
	private static final String DEFAULT_FILTER_TYPE_FOR_STRING = "StringFilter";
	private static final String DEFAULT_FILTER_TYPE_FOR_BOOLEAN = "BooleanFilter";
	private static final String DEFAULT_FILTER_TYPE_FOR_LONG = "LongFilter";

	// REPORT
	private static final String DEFAULT_REPORT_TYPE_FOR_LONG = "java.lang.Long";
	private static final String DEFAULT_REPORT_TYPE_FOR_CODE = "java.lang.Integer";
	private static final String DEFAULT_REPORT_TYPE_FOR_FLAG = "java.lang.Boolean";
	private static final String DEFAULT_REPORT_TYPE_FOR_VALUE = "java.math.BigDecimal";
	private static final String DEFAULT_REPORT_TYPE_FOR_NUMBER = "java.lang.Integer";
	private static final String DEFAULT_REPORT_TYPE_FOR_STRING = "java.lang.String";
	private static final String DEFAULT_REPORT_TYPE_FOR_INTEGER = "java.lang.Integer";
	private static final String DEFAULT_REPORT_TYPE_FOR_BOOLEAN = "java.lang.Boolean";
	private static final String DEFAULT_REPORT_TYPE_FOR_DATE = "java.time.LocalDate";
	private static final String DEFAULT_REPORT_TYPE_FOR_DATETIME = "java.time.LocalDateTime";
	private static final String DEFAULT_REPORT_TYPE_FOR_CURRENCY = "java.math.BigDecimal";
	
	private static final String DEFAULT_FIELDTYPE_FOR_DATE = "FieldType.DATE_TIME";
	private static final String DEFAULT_FIELDTYPE_FOR_DATETIME = "FieldType.DATE_TIME";
	private static final String DEFAULT_FIELDTYPE_FOR_NUMBER = "FieldType.INT32";
	private static final String DEFAULT_FIELDTYPE_FOR_CODE = "FieldType.INT32";
	private static final String DEFAULT_FIELDTYPE_FOR_VALUE = "FieldType.DOUBLE";
	private static final String DEFAULT_FIELDTYPE_FOR_CURRENCY = "FieldType.DOUBLE";
	private static final String DEFAULT_FIELDTYPE_FOR_STRING = "FieldType.STRING";
	private static final String DEFAULT_FIELDTYPE_FOR_BOOLEAN = "FieldType.BOOLEAN";
	private static final String DEFAULT_FIELDTYPE_FOR_LONG = "Long";
	private static final String DEFAULT_FIELDTYPE_FOR_BLOB = "byte[]";
	private static final String DEFAULT_FIELDTYPE_FOR_LOB = "FieldType.STRING";
	private static final String DEFAULT_FIELDTYPE_FOR_CLOB = "FieldType.STRING";

	// MAP
	private static Map<String, String> MAP_DEFAULT_JAVA_TYPE = new HashMap<>();
	private static Map<String, String> MAP_DEFAULT_ANGULAR_TYPE = new HashMap<>();
	private static Map<String, String> MAP_DEFAULT_FILTER_TYPE = new HashMap<>();
	private static Map<String, String> MAP_DEFAULT_SQL_TYPE = new HashMap<>();
	private static Map<String, String> MAP_DEFAULT_SQL_LENGTH = new HashMap<>();
	private static Map<String, String> MAP_DEFAULT_REPORT_TYPE = new HashMap<>();
	private static Map<String, String> MAP_DEFAULT_FIELD_TYPE = new HashMap<>();
	private static Collection<String> NOT_FILTRABLE_TYPES = new ArrayList<>();

	static {
		MAP_DEFAULT_JAVA_TYPE.put(LONG, DEFAULT_JAVATYPE_FOR_LONG);
		MAP_DEFAULT_JAVA_TYPE.put(CODE, DEFAULT_JAVATYPE_FOR_CODE);
		MAP_DEFAULT_JAVA_TYPE.put(FLAG, DEFAULT_JAVATYPE_FOR_BOOLEAN);
		MAP_DEFAULT_JAVA_TYPE.put(VALUE, DEFAULT_JAVATYPE_FOR_VALUE);
		MAP_DEFAULT_JAVA_TYPE.put(NUMBER, DEFAULT_JAVATYPE_FOR_NUMBER);
		MAP_DEFAULT_JAVA_TYPE.put(STRING, DEFAULT_JAVATYPE_FOR_STRING);
		MAP_DEFAULT_JAVA_TYPE.put(INTEGER, DEFAULT_JAVATYPE_FOR_NUMBER);
		MAP_DEFAULT_JAVA_TYPE.put(BOOLEAN, DEFAULT_JAVATYPE_FOR_BOOLEAN);
		MAP_DEFAULT_JAVA_TYPE.put(CURRENCY, DEFAULT_JAVATYPE_FOR_CURRENCY);
		MAP_DEFAULT_JAVA_TYPE.put(DATETIME, DEFAULT_JAVATYPE_FOR_DATETIME);
		MAP_DEFAULT_JAVA_TYPE.put(DATE, DEFAULT_JAVATYPE_FOR_DATE);
		MAP_DEFAULT_JAVA_TYPE.put(BLOB, DEFAULT_JAVATYPE_FOR_BLOB);
		MAP_DEFAULT_JAVA_TYPE.put(LOB, DEFAULT_JAVATYPE_FOR_LOB);
		MAP_DEFAULT_JAVA_TYPE.put(CLOB, DEFAULT_JAVATYPE_FOR_CLOB);
	}

	static {
		MAP_DEFAULT_ANGULAR_TYPE.put(DATETIME, DEFAULT_ANGULARTYPE_FOR_DATETIME);
		MAP_DEFAULT_ANGULAR_TYPE.put(DATE, DEFAULT_ANGULARTYPE_FOR_DATE);
		MAP_DEFAULT_ANGULAR_TYPE.put(NUMBER, DEFAULT_ANGULARTYPE_FOR_NUMBER);
		MAP_DEFAULT_ANGULAR_TYPE.put(INTEGER, DEFAULT_ANGULARTYPE_FOR_NUMBER);
		MAP_DEFAULT_ANGULAR_TYPE.put(CODE, DEFAULT_ANGULARTYPE_FOR_CODE);
		MAP_DEFAULT_ANGULAR_TYPE.put(VALUE, DEFAULT_ANGULARTYPE_FOR_VALUE);
		MAP_DEFAULT_ANGULAR_TYPE.put(CURRENCY, DEFAULT_ANGULARTYPE_FOR_CURRENCY);
		MAP_DEFAULT_ANGULAR_TYPE.put(STRING, DEFAULT_ANGULARTYPE_FOR_STRING);
		MAP_DEFAULT_ANGULAR_TYPE.put(BOOLEAN, DEFAULT_ANGULARTYPE_FOR_BOOLEAN);
		MAP_DEFAULT_ANGULAR_TYPE.put(LONG, DEFAULT_ANGULARTYPE_FOR_LONG);
		MAP_DEFAULT_ANGULAR_TYPE.put(FLAG, DEFAULT_ANGULARTYPE_FOR_BOOLEAN);
	}

	static {
		MAP_DEFAULT_FILTER_TYPE.put(DATETIME, DEFAULT_FILTER_TYPE_FOR_DATETIME);
		MAP_DEFAULT_FILTER_TYPE.put(DATE, DEFAULT_FILTER_TYPE_FOR_DATE);
		MAP_DEFAULT_FILTER_TYPE.put(NUMBER, DEFAULT_FILTER_TYPE_FOR_NUMBER);
		MAP_DEFAULT_FILTER_TYPE.put(INTEGER, DEFAULT_FILTER_TYPE_FOR_NUMBER);
		MAP_DEFAULT_FILTER_TYPE.put(CODE, DEFAULT_FILTER_TYPE_FOR_CODE);
		MAP_DEFAULT_FILTER_TYPE.put(VALUE, DEFAULT_FILTER_TYPE_FOR_VALUE);
		MAP_DEFAULT_FILTER_TYPE.put(CURRENCY, DEFAULT_FILTER_TYPE_FOR_CURRENCY);
		MAP_DEFAULT_FILTER_TYPE.put(STRING, DEFAULT_FILTER_TYPE_FOR_STRING);
		MAP_DEFAULT_FILTER_TYPE.put(BOOLEAN, DEFAULT_FILTER_TYPE_FOR_BOOLEAN);
		MAP_DEFAULT_FILTER_TYPE.put(LONG, DEFAULT_FILTER_TYPE_FOR_LONG);
		MAP_DEFAULT_FILTER_TYPE.put(FLAG, DEFAULT_FILTER_TYPE_FOR_BOOLEAN);
	}

	static {
		MAP_DEFAULT_SQL_TYPE.put(DATETIME, DEFAULT_SQLTYPE_FOR_DATETIME);
		MAP_DEFAULT_SQL_TYPE.put(DATE, DEFAULT_SQLTYPE_FOR_DATE);
		MAP_DEFAULT_SQL_TYPE.put(NUMBER, DEFAULT_SQLTYPE_FOR_NUMBER);
		MAP_DEFAULT_SQL_TYPE.put(INTEGER, DEFAULT_SQLTYPE_FOR_NUMBER);
		MAP_DEFAULT_SQL_TYPE.put(CODE, DEFAULT_SQLTYPE_FOR_CODE);
		MAP_DEFAULT_SQL_TYPE.put(VALUE, DEFAULT_SQLTYPE_FOR_VALUE);
		MAP_DEFAULT_SQL_TYPE.put(CURRENCY, DEFAULT_SQLTYPE_FOR_CURRENCY);
		MAP_DEFAULT_SQL_TYPE.put(STRING, DEFAULT_SQLTYPE_FOR_STRING);
		MAP_DEFAULT_SQL_TYPE.put(BOOLEAN, DEFAULT_SQLTYPE_FOR_BOOLEAN);
		MAP_DEFAULT_SQL_TYPE.put(LONG, DEFAULT_SQLTYPE_FOR_LONG);
		MAP_DEFAULT_SQL_TYPE.put(FLAG, DEFAULT_SQLTYPE_FOR_BOOLEAN);
		MAP_DEFAULT_SQL_TYPE.put(LOB, DEFAULT_SQLTYPE_FOR_LOB);
		MAP_DEFAULT_SQL_TYPE.put(BLOB, DEFAULT_SQLTYPE_FOR_BLOB);
		MAP_DEFAULT_SQL_TYPE.put(CLOB, DEFAULT_SQLTYPE_FOR_CLOB);
	}

	static {
		MAP_DEFAULT_SQL_LENGTH.put(DATETIME, DEFAULT_SQLLENGTH_FOR_DATETIME);
		MAP_DEFAULT_SQL_LENGTH.put(DATE, DEFAULT_SQLLENGTH_FOR_DATE);
		MAP_DEFAULT_SQL_LENGTH.put(NUMBER, DEFAULT_SQLLENGTH_FOR_NUMBER);
		MAP_DEFAULT_SQL_LENGTH.put(INTEGER, DEFAULT_SQLLENGTH_FOR_NUMBER);
		MAP_DEFAULT_SQL_LENGTH.put(CODE, DEFAULT_SQLLENGTH_FOR_CODE);
		MAP_DEFAULT_SQL_LENGTH.put(VALUE, DEFAULT_SQLLENGTH_FOR_VALUE);
		MAP_DEFAULT_SQL_LENGTH.put(CURRENCY, DEFAULT_SQLLENGTH_FOR_CURRENCY);
		MAP_DEFAULT_SQL_LENGTH.put(STRING, DEFAULT_SQLLENGTH_FOR_STRING);
		MAP_DEFAULT_SQL_LENGTH.put(BOOLEAN, DEFAULT_SQLLENGTH_FOR_BOOLEAN);
		MAP_DEFAULT_SQL_LENGTH.put(LONG, DEFAULT_SQLLENGTH_FOR_LONG);
		MAP_DEFAULT_SQL_LENGTH.put(FLAG, DEFAULT_SQLLENGTH_FOR_BOOLEAN);
		MAP_DEFAULT_SQL_LENGTH.put(LOB, DEFAULT_SQLLENGTH_FOR_LOB);
		MAP_DEFAULT_SQL_LENGTH.put(BLOB, DEFAULT_SQLLENGTH_FOR_BLOB);
		MAP_DEFAULT_SQL_LENGTH.put(CLOB, DEFAULT_SQLLENGTH_FOR_CLOB);
	}

	static {
		MAP_DEFAULT_REPORT_TYPE.put(LONG, DEFAULT_REPORT_TYPE_FOR_LONG);
		MAP_DEFAULT_REPORT_TYPE.put(CODE, DEFAULT_REPORT_TYPE_FOR_CODE);
		MAP_DEFAULT_REPORT_TYPE.put(FLAG, DEFAULT_REPORT_TYPE_FOR_FLAG);
		MAP_DEFAULT_REPORT_TYPE.put(VALUE, DEFAULT_REPORT_TYPE_FOR_VALUE);
		MAP_DEFAULT_REPORT_TYPE.put(NUMBER, DEFAULT_REPORT_TYPE_FOR_NUMBER);
		MAP_DEFAULT_REPORT_TYPE.put(STRING, DEFAULT_REPORT_TYPE_FOR_STRING);
		MAP_DEFAULT_REPORT_TYPE.put(INTEGER, DEFAULT_REPORT_TYPE_FOR_INTEGER);
		MAP_DEFAULT_REPORT_TYPE.put(BOOLEAN, DEFAULT_REPORT_TYPE_FOR_BOOLEAN);
		MAP_DEFAULT_REPORT_TYPE.put(CURRENCY, DEFAULT_REPORT_TYPE_FOR_CURRENCY);
		MAP_DEFAULT_REPORT_TYPE.put(DATETIME, DEFAULT_REPORT_TYPE_FOR_DATETIME);
		MAP_DEFAULT_REPORT_TYPE.put(DATE, DEFAULT_REPORT_TYPE_FOR_DATE);
	}
	
	static {
		MAP_DEFAULT_FIELD_TYPE.put(LONG, DEFAULT_FIELDTYPE_FOR_LONG);
		MAP_DEFAULT_FIELD_TYPE.put(CODE, DEFAULT_FIELDTYPE_FOR_CODE);
		MAP_DEFAULT_FIELD_TYPE.put(FLAG, DEFAULT_FIELDTYPE_FOR_BOOLEAN);
		MAP_DEFAULT_FIELD_TYPE.put(VALUE, DEFAULT_FIELDTYPE_FOR_VALUE);
		MAP_DEFAULT_FIELD_TYPE.put(NUMBER, DEFAULT_FIELDTYPE_FOR_NUMBER);
		MAP_DEFAULT_FIELD_TYPE.put(STRING, DEFAULT_FIELDTYPE_FOR_STRING);
		MAP_DEFAULT_FIELD_TYPE.put(INTEGER, DEFAULT_FIELDTYPE_FOR_NUMBER);
		MAP_DEFAULT_FIELD_TYPE.put(BOOLEAN, DEFAULT_FIELDTYPE_FOR_BOOLEAN);
		MAP_DEFAULT_FIELD_TYPE.put(CURRENCY, DEFAULT_FIELDTYPE_FOR_CURRENCY);
		MAP_DEFAULT_FIELD_TYPE.put(DATETIME, DEFAULT_FIELDTYPE_FOR_DATETIME);
		MAP_DEFAULT_FIELD_TYPE.put(DATE, DEFAULT_FIELDTYPE_FOR_DATE);
		MAP_DEFAULT_FIELD_TYPE.put(BLOB, DEFAULT_FIELDTYPE_FOR_BLOB);
		MAP_DEFAULT_FIELD_TYPE.put(LOB, DEFAULT_FIELDTYPE_FOR_LOB);
		MAP_DEFAULT_FIELD_TYPE.put(CLOB, DEFAULT_FIELDTYPE_FOR_CLOB);
	}

	static {
		NOT_FILTRABLE_TYPES.add(LOB);
		NOT_FILTRABLE_TYPES.add(CLOB);
		NOT_FILTRABLE_TYPES.add(BLOB);
	}

	/**
	 * Return mapped java type from umlType
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param type
	 * @return
	 */
	public static String getJavaType(Type type) {
		String umlType = type.getName();
		String javaTypeName = MAP_DEFAULT_JAVA_TYPE.get(umlType);
		if (javaTypeName == null)
			return umlType;
		return javaTypeName;
	}

	/**
	 * Return mapped angular type from umlType
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param type
	 * @return
	 */
	public static String getAngularType(Type type) {
		String umlType = type.getName();
		String angularTypeName = MAP_DEFAULT_ANGULAR_TYPE.get(umlType);
		if (angularTypeName == null)
			return umlType;
		return angularTypeName;
	}

	/**
	 * Return mapped filter type from umlType
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param type
	 * @return
	 */
	public static String getFilterType(Type type) {
		String umlType = type.getName();
		String filterTypeName = MAP_DEFAULT_FILTER_TYPE.get(umlType);
		if (filterTypeName == null)
			return umlType;
		return filterTypeName;
	}

	/**
	 * Return the Filter properties based on property type
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param classe
	 * @return the Filter properties based on property type
	 */
	public String getFilterProperties(Class classe) {
		if (classe == null) {
			return "false";
		}
		String result = "";
		for (Property p : classe.getOwnedAttributes()) {
			result += "private " + getJavaType(p.getType()) + "Filter " + p.getName() + ";\n";
		}
		return result;
	}

	/**
	 * Method to generate filter imports for Criteria
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param classe
	 * @return String containing filter import list
	 */
	public String getFilterImportsFromTypes(Class classe, String filterTypePackage) {
		if (classe == null) {
			return "false";
		}
		String result = "";
		Set<String> attributiSet = new HashSet<>();
		for (Property p : classe.getOwnedAttributes()) {
			attributiSet.add(getJavaType(p.getType()));
		}
		for (Class fClass : AssociationUtils.getParentClasses(classe)) {
			if (!EntityUtils.hasCompositeKey(fClass)) {
				for (Property p : fClass.getAllAttributes()) {
					if (p.isID()) {
						attributiSet.add(getJavaType(p.getType()));
					}
				}
			} else {
				attributiSet.add("");
			}
		}
		for (String att : attributiSet) {
			// For unconventional Filters use this method

			/*
			 * if ("BigDecimal".equals(att)) { result +=
			 * "import it.mice.samplemasterdetail.filter.BigDecimalFilter;\n"; } else if
			 * ("BigDecimal".equals(att)) { result +=
			 * "import it.mice.samplemasterdetail.filter.StringFilter;\n";
			 */
			result += "import " + filterTypePackage + "." + att + "Filter;\n";
		}
		return result;
	}

	/**
	 * Returns "true" if the input type is present in the mapping
	 * 
	 * @author Luca Barone <luca.barone@micegroup.it>
	 * @param type
	 * @return
	 */
	public boolean isPresentJavaType(String type) {
		String javaTypeName = MAP_DEFAULT_JAVA_TYPE.get(type);
		if (javaTypeName == null)
			return false;
		return true;
	}

	/**
	 * Return a Set of imports for the properties used
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param classe
	 * @return a Set of imports for the properties used
	 */
	public Set<String> getImportsForProperty(Class classe) {
		Set<String> imports = new HashSet<>();
		for (Property property : classe.getOwnedAttributes()) {
			if (("BigDecimal").equals(getJavaType(property.getType())))
				imports.add("import java.math.BigDecimal;");
			if (("LocalDate").equals(getJavaType(property.getType())))
				imports.add("import java.time.LocalDate;");
			if (("LocalDateTime").equals(getJavaType(property.getType())))
				imports.add("import java.time.LocalDateTime;\n import com.fasterxml.jackson.annotation.JsonFormat;");
			if (("Date").equals(getJavaType(property.getType())))
				imports.add("import java.util.Date;");
			if (PropertyUtils.isRequired(property))
				imports.add("import javax.validation.constraints.NotNull;");
		}
		return imports;
	}

	/**
	 * Return the collection of class attribute without duplicates
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param classe
	 * @return
	 */
	public static Collection<Type> getAttributeTypesNoDuplicates(Class classe) {
		LinkedHashSet<Type> hashSet = new LinkedHashSet<>();
		for (Property property : EntityUtils.getIdAttributesFromForeignKeys(classe)) {
			hashSet.add(property.getType());
		}

		for (Property property : classe.getOwnedAttributes()) {
			hashSet.add(property.getType());
		}
		return new ArrayList<Type>(hashSet);
	}

	/**
	 * Return the collection of class attribute java type without duplicates
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param classe
	 * @return
	 */
	public static Collection<String> getAttributeJavaTypesNoDuplicates(Collection<Property> attributi) {
		LinkedHashSet<String> hashSet = new LinkedHashSet<>();

		for (Property property : attributi) {
			hashSet.add(getFilterType(property.getType()));
		}
		return new ArrayList<String>(hashSet);
	}

	/**
	 * Return the collection of class attribute java type without duplicates
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param classe
	 * @return
	 */
	public static Collection<String> getAttributeAngularTypesNoDuplicates(Collection<Property> attributi) {
		LinkedHashSet<String> hashSet = new LinkedHashSet<>();
		for (Property property : attributi) {
			hashSet.add(getFilterType(property.getType()));
		}
		return new ArrayList<String>(hashSet);
	}

	/**
	 * Return mapped sql type from umlType
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param type
	 * @return
	 */
	public static String getSqlType(Type type) {
		String umlType = type.getName();
		String sqlTypeName = MAP_DEFAULT_SQL_TYPE.get(umlType);
		if (sqlTypeName == null)
			return umlType;
		return sqlTypeName;
	}

	/**
	 * Return mapped sql type from umlType
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param type
	 * @return
	 */
	public static String getSqlLength(Property property) {
		String umlType = property.getType().getName();
		String sqlTypeLength = MAP_DEFAULT_SQL_LENGTH.get(umlType);
		String attributeLength = StereotypeUtils.<String, Property>getStereotypeValue(property,
				StereotypeName.ATTRIBUTE, StereotypePropertyName.PHYSICAL_LENGTH);
		if (attributeLength != null && !attributeLength.isEmpty())
			sqlTypeLength = attributeLength;
		if (sqlTypeLength == null)
			return umlType;
		return sqlTypeLength;
	}

	/**
	 * Return report type from UML type.
	 * 
	 * @author Fabio Memoli <fabio.memoli@micegroup.it>
	 * @param type of UML
	 * @return type of report
	 */
	public static String getReportType(Type umlType) {
		String reportType = MAP_DEFAULT_REPORT_TYPE.get(umlType.getName());
		return (reportType == null) ? umlType.getName() : reportType;
	}

	/**
	 * return a set of imports for class specific dto
	 * 
	 * @author Simone Punzo <simone.punzo@micegroup.it>
	 * @param classe
	 * @return required java imports
	 */
	public Set<String> getImportsForPropertyDto(Class classe) {
		Set<String> imports = new HashSet<>();
		for (Property property : classe.getOwnedAttributes()) {
			if (("BigDecimal").equals(getJavaType(property.getType())))
				imports.add("import java.math.BigDecimal;");
			if (("LocalDate").equals(getJavaType(property.getType())))
				imports.add("import java.time.LocalDate;");
			if (("LocalDateTime").equals(getJavaType(property.getType())))
				imports.add("import java.time.LocalDateTime;");
		}
		return imports;
	}

	/**
	 * Ritorna la lista dei tipi non filtrabili nelle ricerche
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 *
	 * @return
	 */
	public static Collection<String> getNotFiltrableTypes() {
		return NOT_FILTRABLE_TYPES;
	}
	
	/**
	 * Return mapped field type from umlType
	 * 
	 * @author Vittorio Niespolo <vittorio.niespolo@micegroup.it>
	 * @param type
	 * @return
	 */
	public static String getFieldType(Type type) {
		String umlType = type.getName();
		String fieldTypeName = MAP_DEFAULT_FIELD_TYPE.get(umlType);
		if (fieldTypeName == null)
			return umlType;
		return fieldTypeName;
	}
	
}
