LQMGNamingStrategy.java
/*
* Copyright (C) 2011 Everit Kft. (http://www.everit.biz)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.everit.persistence.lqmg.internal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.JAXBElement;
import org.everit.persistence.lqmg.LQMGException;
import org.everit.persistence.lqmg.internal.schema.xml.AbstractNamingRuleType;
import org.everit.persistence.lqmg.internal.schema.xml.ClassNameRuleType;
import org.everit.persistence.lqmg.internal.schema.xml.PropertyMappingType;
import org.everit.persistence.lqmg.internal.schema.xml.PropertyMappingsType;
import org.everit.persistence.lqmg.internal.schema.xml.RegexRuleType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.querydsl.codegen.EntityType;
import com.querydsl.sql.SchemaAndTable;
import com.querydsl.sql.codegen.DefaultNamingStrategy;
import com.querydsl.sql.codegen.support.ForeignKeyData;
/**
* Customized {@link com.querydsl.sql.codegen.NamingStrategy} for LQMG.
*/
public class LQMGNamingStrategy extends DefaultNamingStrategy {
/**
* Constants for DB attributes.
*/
private enum DBAttributeType {
COLUMN("column"), FOREIGN_KEY("foreignKey"), PRIMARY_KEY("primaryKey");
private String typeName;
DBAttributeType(final String typeName) {
this.typeName = typeName;
}
public String getTypeName() {
return typeName;
}
}
private static final String FK_PREFIX = "fk_";
private static final Logger LOGGER = LoggerFactory.getLogger(LQMGNamingStrategy.class);
private static final String PK_PREFIX = "pk_";
private final Map<SchemaAndTable, String> classNameCache = new HashMap<>();
private final ConfigurationContainer configurationContainer;
private final Set<String> packages;
public LQMGNamingStrategy(final ConfigurationContainer configurationContainer,
final String[] packages) {
this.configurationContainer = configurationContainer;
this.packages = new HashSet<String>(Arrays.asList(packages));
}
@Override
public String getClassName(final SchemaAndTable schemaAndTable) {
String simpleName = classNameCache.get(schemaAndTable);
if (simpleName != null) {
return simpleName;
}
ConfigValue<? extends AbstractNamingRuleType> configValue =
configurationContainer.findConfigForEntity(schemaAndTable);
if (configValue == null) {
return null;
}
AbstractNamingRuleType namingRule = configValue.namingRule;
if (namingRule instanceof RegexRuleType) {
RegexRuleType regexRule = (RegexRuleType) namingRule;
String regex = regexRule.getRegex();
String replacement = regexRule.getReplacement();
Pattern pattern = configurationContainer.getPatternByRegex(regex);
Matcher matcher = pattern.matcher(schemaAndTable.getTable());
String replacedEntityName = matcher.replaceAll(replacement);
simpleName = super.getClassName(replacedEntityName);
} else if (namingRule instanceof ClassNameRuleType) {
simpleName = ((ClassNameRuleType) namingRule).getClazz();
}
String prefix = namingRule.getPrefix();
if (prefix != null) {
simpleName = prefix + simpleName;
}
String suffix = namingRule.getSuffix();
if (suffix != null) {
simpleName = simpleName + suffix;
}
classNameCache.put(schemaAndTable, simpleName);
if (simpleName == null) {
throw new LQMGException(
"Cannot resolve class name for '" + schemaAndTable.getTable() + "' table in '"
+ schemaAndTable.getSchema() + "' schema.",
null);
}
return simpleName;
}
@Override
public String getDefaultVariableName(final EntityType entityType) {
SchemaAndTable schemaAndTable = getSchemaAndTable(entityType);
String propertyName = getClassName(schemaAndTable);
ConfigValue<? extends AbstractNamingRuleType> config =
configurationContainer.findConfigForEntity(schemaAndTable);
AbstractNamingRuleType namingRule = config.getNamingRule();
String prefix = namingRule.getPrefix();
String suffix = namingRule.getSuffix();
if (prefix != null) {
propertyName = propertyName.substring(prefix.length());
}
if (suffix != null) {
propertyName = propertyName.substring(0, propertyName.length() - suffix.length());
}
propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1);
return escape(entityType, propertyName);
}
private List<JAXBElement<PropertyMappingType>> getForeignKeyAndPrimaryKeyAndColumnForEntity(
final EntityType entityType) {
SchemaAndTable schemaAndTable = getSchemaAndTable(entityType);
ConfigValue<? extends AbstractNamingRuleType> configValue =
configurationContainer.findConfigForEntity(schemaAndTable);
if (configValue == null) {
return null;
}
AbstractNamingRuleType namingRule = configValue.getNamingRule();
if (!(namingRule instanceof ClassNameRuleType)) {
return null;
}
PropertyMappingsType propertyMappings = ((ClassNameRuleType) namingRule).getPropertyMappings();
if (propertyMappings == null) {
return null;
}
return propertyMappings.getPrimaryKeyAndForeignKeyAndColumn();
}
@Override
public String getPackage(final String basePackage, final SchemaAndTable schemaAndTable) {
String simpleName = getClassName(schemaAndTable);
if (simpleName == null) {
throw new LQMGException("Cannot resolve class name for '" + schemaAndTable.getTable()
+ "' table in '" + schemaAndTable.getSchema() + "' schema.", null);
}
ConfigValue<? extends AbstractNamingRuleType> configValue =
configurationContainer.findConfigForEntity(schemaAndTable);
AbstractNamingRuleType namingRule = configValue.getNamingRule();
String packageName = namingRule.getPackage();
return packageName;
}
@Override
public String getPropertyName(final String columnName, final EntityType entityType) {
String propertyName =
getPropertyNameFromMapping(columnName, entityType, DBAttributeType.COLUMN);
if (propertyName != null) {
return propertyName;
} else {
return super.getPropertyName(columnName, entityType);
}
}
@Override
public String getPropertyNameForForeignKey(final String fkName, final EntityType entityType) {
String localFkName = fkName;
String propertyName =
getPropertyNameFromMapping(localFkName, entityType, DBAttributeType.FOREIGN_KEY);
if (propertyName != null) {
return propertyName;
} else {
if (localFkName.toLowerCase(Locale.ENGLISH).startsWith(FK_PREFIX)) {
localFkName = localFkName.substring(FK_PREFIX.length()) + "_" + localFkName.substring(0, 2);
}
return getSuperPropertyName(localFkName, entityType);
}
}
@Override
public String getPropertyNameForPrimaryKey(final String pkName, final EntityType entityType) {
String localPkName = pkName;
String propertyName =
getPropertyNameFromMapping(localPkName, entityType, DBAttributeType.PRIMARY_KEY);
if (propertyName != null) {
return propertyName;
} else {
if (localPkName.toLowerCase(Locale.ENGLISH).startsWith(PK_PREFIX)) {
localPkName = localPkName.substring(PK_PREFIX.length()) + "_" + localPkName.substring(0, 2);
}
return getSuperPropertyName(localPkName, entityType);
}
}
private String getPropertyNameFromMapping(final String originalName,
final EntityType entityType,
final DBAttributeType dbAttributeType) {
List<JAXBElement<PropertyMappingType>> foreignKeyAndPrimaryKeyAndColumn =
getForeignKeyAndPrimaryKeyAndColumnForEntity(entityType);
if (foreignKeyAndPrimaryKeyAndColumn == null) {
return null;
}
PropertyMappingType selectedMapping = null;
Iterator<JAXBElement<PropertyMappingType>> iterator =
foreignKeyAndPrimaryKeyAndColumn.iterator();
while (iterator.hasNext() && (selectedMapping == null)) {
JAXBElement<?> jaxbElement = iterator.next();
if (dbAttributeType.getTypeName().equals(jaxbElement.getName().getLocalPart())) {
PropertyMappingType propertyMapping = (PropertyMappingType) jaxbElement.getValue();
if (propertyMapping.getName().equals(originalName)) {
selectedMapping = propertyMapping;
}
}
}
if (selectedMapping != null) {
return selectedMapping.getProperty();
} else {
return null;
}
}
private SchemaAndTable getSchemaAndTable(final EntityType entityType) {
String tableName = entityType.getData().get("table").toString();
String schemaName = (String) entityType.getData().get("schema");
SchemaAndTable schemaAndTable = new SchemaAndTable(schemaName, tableName);
return schemaAndTable;
}
private String getSuperPropertyName(final String columnName, final EntityType entityType) {
return super.getPropertyName(columnName, entityType);
}
private boolean shouldGenerate(final SchemaAndTable schemaAndTable) {
ConfigValue<? extends AbstractNamingRuleType> configValue =
configurationContainer.findConfigForEntity(schemaAndTable);
if (configValue == null) {
LOGGER.info("No configuration for table '" + schemaAndTable.getTable() + "' in schema '"
+ schemaAndTable.getSchema());
return false;
}
AbstractNamingRuleType namingRule = configValue.getNamingRule();
String javaPackage = namingRule.getPackage();
if ((packages.size() > 0) && !packages.contains(javaPackage)) {
LOGGER.info("Java package '" + javaPackage + "' is not included, ignoring table '"
+ schemaAndTable.getTable() + "' from schema '." + schemaAndTable.getSchema());
return false;
}
return true;
}
@Override
public boolean shouldGenerateClass(final SchemaAndTable schemaAndTable) {
if (shouldGenerate(schemaAndTable)) {
return super.shouldGenerateClass(schemaAndTable);
}
return false;
}
@Override
public boolean shouldGenerateForeignKey(final SchemaAndTable schemaAndTable,
final ForeignKeyData foreignKeyData) {
String fkSchemaName = foreignKeyData.getSchema();
String fkTableName = foreignKeyData.getTable();
SchemaAndTable fkSchemaAndTable = new SchemaAndTable(fkSchemaName, fkTableName);
if (shouldGenerate(fkSchemaAndTable)) {
return super.shouldGenerateForeignKey(schemaAndTable, foreignKeyData);
}
return false;
}
}