package com.txtr.hibernatedelta.validator; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; import javax.persistence.Table; import org.apache.commons.lang3.StringUtils; import org.hibernate.annotations.NotFound; import com.txtr.hibernatedelta.model.HibernateModelUtil; import com.txtr.hibernatedelta.model.OracleKeywords; import com.txtr.hibernatedelta.model.VirtualRootTable; public class HibernateValidator { public static final int DISCRIMINATOR_LENGTH = 128; static void validateTable(Class<?> entity) { Table table = entity.getAnnotation(Table.class); DiscriminatorValue discriminatorValue = entity.getAnnotation(DiscriminatorValue.class); Inheritance inheritance = entity.getAnnotation(Inheritance.class); DiscriminatorColumn discriminatorColumn = entity.getAnnotation(DiscriminatorColumn.class); if (discriminatorColumn != null) { if (discriminatorColumn.discriminatorType() != DiscriminatorType.STRING) { throw new IllegalStateException("DiscriminatorColumn.discriminatorType must 'DiscriminatorType.STRING': " + entity); } if (discriminatorColumn.length() != DISCRIMINATOR_LENGTH) { throw new IllegalStateException("DiscriminatorColumn.length must be 128: " + entity); } } if (HibernateModelUtil.isTableRoot(entity)) { validateRootTable(entity, table, discriminatorValue, inheritance, discriminatorColumn); } else { validateNonRootTable(entity, table, discriminatorValue, inheritance, discriminatorColumn); } if (table != null){ checkTableName(entity, table); } } private static void checkTableName(Class<?> entity, Table table) { final String tableName = table.name(); final String entityName = entity.getSimpleName(); if (entityName.length() <= 28){ if (tableName.toLowerCase().endsWith("table")){ if (! StringUtils.substringBefore(tableName.toLowerCase(), "table").equalsIgnoreCase(entityName)){ throw new IllegalStateException("table name " + tableName + " of entity " + entity + " doesn't match"); } } else { if (! tableName.equalsIgnoreCase(entityName)){ throw new IllegalStateException("table name " + tableName + " of entity " + entity + " doesn't match"); } } } //else: too long table names can't be checked algorithmically } private static void validateNonRootTable(Class<?> entity, Table table, DiscriminatorValue discriminatorValue, Inheritance inheritance, DiscriminatorColumn discriminatorColumn) { if (inheritance != null) { throw new IllegalStateException("inheritance must be null: " + entity); } if (discriminatorColumn != null) { throw new IllegalStateException("DiscriminatorColumn must be null: " + entity); } InheritanceType type = HibernateModelUtil.getInheritance(entity); checkDiscriminatorValue(entity, discriminatorValue, type); if (type == InheritanceType.SINGLE_TABLE) { if (table != null) { throw new IllegalStateException("table must be null: " + entity); } } else { if (table == null) { throw new IllegalStateException("table annotation missing: " + entity); } } } private static void validateRootTable(Class<?> entity, Table table, DiscriminatorValue discriminatorValue, Inheritance inheritance, DiscriminatorColumn discriminatorColumn) { if (table == null && entity.getAnnotation(VirtualRootTable.class) == null) { throw new IllegalStateException("table annotation missing: " + entity); } if (inheritance != null) { if (inheritance.strategy() == InheritanceType.SINGLE_TABLE) { if (discriminatorColumn == null) { throw new IllegalStateException("DiscriminatorColumn must not be null: " + entity); } } else { if (discriminatorColumn != null) { throw new IllegalStateException("DiscriminatorColumn must be null: " + entity); } } checkDiscriminatorValue(entity, discriminatorValue, inheritance.strategy()); } } private static void checkDiscriminatorValue(Class<?> entity, DiscriminatorValue discriminatorValue, InheritanceType type) { if (type == InheritanceType.SINGLE_TABLE && !isAbstractClass(entity)) { if (discriminatorValue == null) { throw new IllegalStateException("entity with inheritance and without discriminator value: " + entity); } } else { if (discriminatorValue != null) { throw new IllegalStateException("entity doesn't need a discriminator discriminator value: " + entity); } } } public static boolean isAbstractClass(Class<?> clazz) { int modifier = clazz.getModifiers(); return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier); } static void validateColumn(Class<?> entity, Field field) { String name = entity.getName() + "." + field.getName(); GeneratedValue generatedValue = field.getAnnotation(GeneratedValue.class); if (generatedValue != null) { if (generatedValue.strategy() != GenerationType.AUTO) { throw new IllegalStateException("strategy must be auto: " + name); } if (StringUtils.isNotBlank(generatedValue.generator())) { throw new IllegalStateException("generator must be null: " + name); } } Column column = field.getAnnotation(Column.class); if (column != null) { if (field.getType().equals(String.class) && column.length() > 4000) { throw new IllegalStateException("varchar greater than 4000: " + name); } if (StringUtils.isNotBlank(column.name()) && ! OracleKeywords.KEYWORDS.contains(field.getName()) && field.getName().length() <= 28){ if (column.name().toLowerCase().endsWith("_id")){ if (! StringUtils.substringBefore(column.name().toLowerCase(), "_id").equalsIgnoreCase(field.getName())){ throw new IllegalStateException("column/field name mismatch: " + name); } } else { if (! column.name().equalsIgnoreCase(field.getName())){ throw new IllegalStateException("column/field name mismatch: " + name); } } } } NotFound notFound = field.getAnnotation(NotFound.class); if (notFound != null){ throw new IllegalStateException("@NotFound annotation on " + name); } final JoinColumn joinColumn = field.getAnnotation(JoinColumn.class); if (joinColumn != null && StringUtils.isNotBlank(joinColumn.name())){ if (field.getName().length() <= 25 && ! (field.getName() + "_id").equalsIgnoreCase(joinColumn.name())){ throw new IllegalStateException("JoinColumn name mismatch: " + name); } } } public static String getFullName(final Field field) { return field.getDeclaringClass().getName() + "." + field.getName(); } }