
org.jooq.util.GeneratorStrategyWrapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jooq-codegen Show documentation
Show all versions of jooq-codegen Show documentation
jOOQ's source code generator
/**
* Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
* All rights reserved.
*
* 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.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.util;
import static org.jooq.util.GenerationUtil.convertToIdentifier;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jooq.Record;
import org.jooq.impl.AbstractRoutine;
import org.jooq.impl.TableRecordImpl;
import org.jooq.impl.UDTRecordImpl;
import org.jooq.impl.UpdatableRecordImpl;
import org.jooq.tools.StringUtils;
import org.jooq.util.AbstractGenerator.Language;
/**
* A wrapper for generator strategies preventing some common compilation errors
* resulting from badly generated source code
*
* @author Lukas Eder
*/
class GeneratorStrategyWrapper extends AbstractGeneratorStrategy {
private final Map, Set> reservedColumns = new HashMap, Set>();
final Generator generator;
final GeneratorStrategy delegate;
final Language language;
GeneratorStrategyWrapper(Generator generator, GeneratorStrategy delegate, Language language) {
this.generator = generator;
this.delegate = delegate;
this.language = language;
}
@Override
public String getTargetDirectory() {
return delegate.getTargetDirectory();
}
@Override
public void setTargetDirectory(String directory) {
delegate.setTargetDirectory(directory);
}
@Override
public String getTargetPackage() {
return delegate.getTargetPackage();
}
@Override
public void setTargetPackage(String packageName) {
delegate.setTargetPackage(packageName);
}
@Override
public void setInstanceFields(boolean instanceFields) {
delegate.setInstanceFields(instanceFields);
}
@Override
public boolean getInstanceFields() {
return delegate.getInstanceFields();
}
@Override
public String getJavaIdentifier(Definition definition) {
// [#1473] Identity identifiers should not be renamed by custom strategies
if (definition instanceof IdentityDefinition)
return "IDENTITY_" + getJavaIdentifier(((IdentityDefinition) definition).getColumn().getContainer());
// [#2032] Intercept default Catalog
else if (definition instanceof CatalogDefinition && ((CatalogDefinition) definition).isDefaultCatalog())
return "DEFAULT_CATALOG";
// [#2089] Intercept default schema
else if (definition instanceof SchemaDefinition && ((SchemaDefinition) definition).isDefaultSchema())
return "DEFAULT_SCHEMA";
String identifier = convertToIdentifier(delegate.getJavaIdentifier(definition), language);
// [#1212] Don't trust custom strategies and disambiguate identifiers here
if (definition instanceof ColumnDefinition ||
definition instanceof AttributeDefinition) {
TypedElementDefinition> e = (TypedElementDefinition>) definition;
if (identifier.equals(getJavaIdentifier(e.getContainer())))
return identifier + "_";
// [#2781] Disambiguate collisions with the leading package name
if (identifier.equals(getJavaPackageName(e.getContainer()).replaceAll("\\..*", "")))
return identifier + "_";
}
else if (definition instanceof TableDefinition) {
SchemaDefinition schema = definition.getSchema();
if (identifier.equals(getJavaIdentifier(schema)))
return identifier + "_";
}
return identifier;
}
@Override
public String getJavaSetterName(Definition definition, Mode mode) {
return disambiguateMethod(definition,
convertToIdentifier(delegate.getJavaSetterName(definition, mode), language));
}
@Override
public String getJavaGetterName(Definition definition, Mode mode) {
return disambiguateMethod(definition,
convertToIdentifier(delegate.getJavaGetterName(definition, mode), language));
}
@Override
public String getJavaMethodName(Definition definition, Mode mode) {
String methodName;
methodName = delegate.getJavaMethodName(definition, mode);
methodName = overload(definition, mode, methodName);
methodName = convertToIdentifier(methodName, language);
return disambiguateMethod(definition, methodName);
}
/**
* [#1358] Add an overload suffix if needed
*/
private String overload(Definition definition, Mode mode, String identifier) {
if (!StringUtils.isBlank(definition.getOverload())) {
identifier += getOverloadSuffix(definition, mode, definition.getOverload());
}
return identifier;
}
/**
* [#182] Method name disambiguation is important to avoid name clashes due
* to pre-existing getters / setters in super classes
*/
private String disambiguateMethod(Definition definition, String method) {
Set reserved = null;
if (definition instanceof AttributeDefinition) {
reserved = reservedColumns(UDTRecordImpl.class);
}
else if (definition instanceof ColumnDefinition) {
if (((ColumnDefinition) definition).getContainer().getPrimaryKey() != null) {
reserved = reservedColumns(UpdatableRecordImpl.class);
}
else {
reserved = reservedColumns(TableRecordImpl.class);
}
}
// [#1406] Disambiguate also procedure parameters
else if (definition instanceof ParameterDefinition) {
reserved = reservedColumns(AbstractRoutine.class);
}
if (reserved != null) {
if (reserved.contains(method)) {
return method + "_";
}
// If this is the setter, check if the getter needed disambiguation
// This ensures that getters and setters have the same name
if (method.startsWith("set")) {
String base = method.substring(3);
if (reserved.contains("get" + base) || reserved.contains("is" + base)) {
return method + "_";
}
}
}
return method;
}
/**
* [#182] Find all column names that are reserved because of the extended
* class hierarchy of a generated class
*/
private Set reservedColumns(Class> clazz) {
if (clazz == null) {
return Collections.emptySet();
}
Set result = reservedColumns.get(clazz);
if (result == null) {
result = new HashSet();
reservedColumns.put(clazz, result);
// Recurse up in class hierarchy
result.addAll(reservedColumns(clazz.getSuperclass()));
for (Class> c : clazz.getInterfaces()) {
result.addAll(reservedColumns(c));
}
for (Method m : clazz.getDeclaredMethods()) {
String name = m.getName();
if (name.startsWith("get") && m.getParameterTypes().length == 0) {
result.add(name);
}
}
}
return result;
}
@Override
public String getJavaClassExtends(Definition definition, Mode mode) {
// [#1243] Only POJO mode can accept super classes
return delegate.getJavaClassExtends(definition, mode);
}
@Override
public List getJavaClassImplements(Definition definition, Mode mode) {
// [#1243] All generation modes can accept interfaces
Set result = new LinkedHashSet(delegate.getJavaClassImplements(definition, mode));
// [#1528] Generated interfaces (implemented by RECORD and POJO) are
// always Serializable
if (mode == Mode.INTERFACE) {
result.add(Serializable.class.getName());
}
// [#1528] POJOs only implement Serializable if they don't inherit
// Serializable from INTERFACE already
else if (mode == Mode.POJO && !generator.generateInterfaces()) {
result.add(Serializable.class.getName());
}
return new ArrayList(result);
}
@Override
public String getJavaClassName(Definition definition, Mode mode) {
// [#1150] Intercept Mode.RECORD calls for tables
if (definition instanceof TableDefinition && !generator.generateRecords() && mode == Mode.RECORD) {
return Record.class.getSimpleName();
}
// [#2032] Intercept default catalog
else if (definition instanceof CatalogDefinition && ((CatalogDefinition) definition).isDefaultCatalog()) {
return "DefaultCatalog";
}
// [#2089] Intercept default schema
else if (definition instanceof SchemaDefinition && ((SchemaDefinition) definition).isDefaultSchema()) {
return "DefaultSchema";
}
String className;
className = delegate.getJavaClassName(definition, mode);
className = overload(definition, mode, className);
className = convertToIdentifier(className, language);
return className;
}
@Override
public String getJavaPackageName(Definition definition, Mode mode) {
// [#1150] Intercept Mode.RECORD calls for tables
if (!generator.generateRecords() && mode == Mode.RECORD && definition instanceof TableDefinition) {
return Record.class.getPackage().getName();
}
String[] split = delegate.getJavaPackageName(definition, mode).split("\\.");
for (int i = 0; i < split.length; i++) {
split[i] = convertToIdentifier(split[i], language);
}
return StringUtils.join(split, ".");
}
@Override
public String getJavaMemberName(Definition definition, Mode mode) {
String identifier = convertToIdentifier(delegate.getJavaMemberName(definition, mode), language);
// [#2781] Disambiguate collisions with the leading package name
if (identifier.equals(getJavaPackageName(definition, mode).replaceAll("\\..*", ""))) {
return identifier + "_";
}
return identifier;
}
@Override
public String getOverloadSuffix(Definition definition, Mode mode, String overloadIndex) {
return delegate.getOverloadSuffix(definition, mode, overloadIndex);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy