Adding dynamic name mapping functionality (#2007)

This commit is contained in:
Balazs Zsoldos 2016-09-05 21:43:33 +02:00
parent 63f25d60b1
commit c6b2decaa1
7 changed files with 248 additions and 35 deletions

View File

@ -26,10 +26,14 @@ import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.primitives.Primitives;
import com.querydsl.core.types.Path;
import com.querydsl.sql.namemapping.ChainedNameMapping;
import com.querydsl.sql.namemapping.NameMapping;
import com.querydsl.sql.namemapping.PreConfiguredNameMapping;
import com.querydsl.sql.types.ArrayType;
import com.querydsl.sql.types.Null;
import com.querydsl.sql.types.Type;
@ -50,7 +54,11 @@ public final class Configuration {
private final JavaTypeMapping javaTypeMapping = new JavaTypeMapping();
private final NameMapping nameMapping = new NameMapping();
private final PreConfiguredNameMapping internalNameMapping = new PreConfiguredNameMapping();
private NameMapping nameMapping = internalNameMapping;
private final Map<String, String> schemaMapping = Maps.newHashMap();
private final Map<String, Class<?>> typeToName = Maps.newHashMap();
@ -196,7 +204,11 @@ public final class Configuration {
*/
@Nullable
public SchemaAndTable getOverride(SchemaAndTable key) {
return nameMapping.getOverride(key);
SchemaAndTable result = nameMapping.getOverride(key).or(key);
if (schemaMapping.containsKey(key.getSchema())) {
result = new SchemaAndTable(schemaMapping.get(key.getSchema()), result.getTable());
}
return result;
}
/**
@ -207,7 +219,24 @@ public final class Configuration {
* @return overridden column
*/
public String getColumnOverride(SchemaAndTable key, String column) {
return nameMapping.getColumnOverride(key, column);
return nameMapping.getColumnOverride(key, column).or(column);
}
/**
* Programmers can specify name mappings by implementing the
* {@link NameMapping} interface. The mapping rules that are specified by
* this property are checked if no mapping is specified by any of the
* <code>register*Override</code> functions.
*
* @param nameMapping
* The name mapping that is implemented by the user.
*/
public void setDynamicNameMapping(NameMapping nameMapping) {
if (nameMapping == null) {
this.nameMapping = this.internalNameMapping;
} else {
this.nameMapping = new ChainedNameMapping(this.nameMapping, nameMapping);
}
}
/**
@ -290,7 +319,7 @@ public final class Configuration {
* @return previous override value
*/
public String registerSchemaOverride(String oldSchema, String newSchema) {
return nameMapping.registerSchemaOverride(oldSchema, newSchema);
return schemaMapping.put(oldSchema, newSchema);
}
/**
@ -301,7 +330,7 @@ public final class Configuration {
* @return previous override value
*/
public String registerTableOverride(String oldTable, String newTable) {
return nameMapping.registerTableOverride(oldTable, newTable);
return internalNameMapping.registerTableOverride(oldTable, newTable);
}
/**
@ -338,7 +367,7 @@ public final class Configuration {
* @return previous override
*/
public SchemaAndTable registerTableOverride(SchemaAndTable from, SchemaAndTable to) {
return nameMapping.registerTableOverride(from, to);
return internalNameMapping.registerTableOverride(from, to);
}
/**
@ -351,7 +380,7 @@ public final class Configuration {
* @return previous override
*/
public String registerColumnOverride(String schema, String table, String oldColumn, String newColumn) {
return nameMapping.registerColumnOverride(schema, table, oldColumn, newColumn);
return internalNameMapping.registerColumnOverride(schema, table, oldColumn, newColumn);
}
/**
@ -363,7 +392,7 @@ public final class Configuration {
* @return previous override
*/
public String registerColumnOverride(String table, String oldColumn, String newColumn) {
return nameMapping.registerColumnOverride(table, oldColumn, newColumn);
return internalNameMapping.registerColumnOverride(table, oldColumn, newColumn);
}
/**

View File

@ -0,0 +1,61 @@
/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* 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 com.querydsl.sql.namemapping;
import com.google.common.base.Optional;
import com.querydsl.sql.SchemaAndTable;
/**
* A {@link NameMapping} implementation that accepts zero or more
* {@link NameMapping}s and returns the first non-null mapping result.
*/
public class ChainedNameMapping implements NameMapping {
private NameMapping[] nameMappings;
public ChainedNameMapping(NameMapping... nameMappings) {
if (nameMappings == null) {
throw new NullPointerException("Name mapping array must not be null");
}
for (NameMapping nameMapping : nameMappings) {
if (nameMapping == null) {
throw new NullPointerException("Name mapping array must not contain null element");
}
}
this.nameMappings = nameMappings.clone();
}
@Override
public Optional<String> getColumnOverride(SchemaAndTable key, String column) {
for (NameMapping nameMapping : nameMappings) {
Optional<String> overriddenColumnName = nameMapping.getColumnOverride(key, column);
if (overriddenColumnName.isPresent()) {
return overriddenColumnName;
}
}
return Optional.absent();
}
@Override
public Optional<SchemaAndTable> getOverride(SchemaAndTable key) {
for (NameMapping nameMapping : nameMappings) {
Optional<SchemaAndTable> overridden = nameMapping.getOverride(key);
if (overridden.isPresent()) {
return overridden;
}
}
return Optional.absent();
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* 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 com.querydsl.sql.namemapping;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.querydsl.sql.SchemaAndTable;
/**
* Simple implementation of {@link NameMapping} that changes the letter-case
* (lower-case or upper-case) of the schema, table and column names. The
* information how the database stores the identifiers are available normally
* from the <code>stores*Identifiers</code> function of the
* {@link java.sql.DatabaseMetaData}
*/
public class ChangeCaseNameMapping implements NameMapping {
/**
* The target letter-case (lower or upper) that the
* {@link ChangeCaseNameMapping} should use to convert the identifiers
* names.
*/
public enum LetterCase {
LOWER, UPPER
}
private final LetterCase targetCase;
public ChangeCaseNameMapping(LetterCase targetCase) {
this.targetCase = Preconditions.checkNotNull(targetCase);
}
@Override
public Optional<String> getColumnOverride(SchemaAndTable key, String column) {
return Optional.of(column.toUpperCase());
}
@Override
public Optional<SchemaAndTable> getOverride(SchemaAndTable key) {
String schema = key.getSchema();
if (schema != null) {
schema = schema.toUpperCase();
}
return Optional.of(new SchemaAndTable(targetCaseOrNull(key.getSchema()), targetCaseOrNull(key.getTable())));
}
private String targetCaseOrNull(String text) {
if (text == null) {
return null;
}
if (targetCase == LetterCase.LOWER) {
return text.toLowerCase();
} else {
return text.toUpperCase();
}
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* 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 com.querydsl.sql.namemapping;
import com.google.common.base.Optional;
import com.querydsl.sql.SchemaAndTable;
/**
* By implementing this interface, it is possible to programmatically override
* schema, table and column names.
*/
public interface NameMapping {
Optional<String> getColumnOverride(SchemaAndTable key, String column);
Optional<SchemaAndTable> getOverride(SchemaAndTable key);
}

View File

@ -11,61 +11,54 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.querydsl.sql;
package com.querydsl.sql.namemapping;
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.Optional;
import com.google.common.collect.Maps;
import com.querydsl.sql.SchemaAndTable;
final class NameMapping {
/**
* {@link NameMapping} implementation that allows specifying exact schema, table and column name mappings.
*/
public class PreConfiguredNameMapping implements NameMapping {
private final Map<SchemaAndTable, SchemaAndTable> schemaTables = Maps.newHashMap();
private final Map<String, String> schemas = Maps.newHashMap();
private final Map<String, String> tables = Maps.newHashMap();
private final Map<SchemaAndTable, Map<String, String>> schemaTableColumns = Maps.newHashMap();
private final Map<String, Map<String, String>> tableColumns = Maps.newHashMap();
public SchemaAndTable getOverride(SchemaAndTable key) {
public Optional<SchemaAndTable> getOverride(SchemaAndTable key) {
if (!schemaTables.isEmpty() && key.getSchema() != null) {
if (schemaTables.containsKey(key)) {
return schemaTables.get(key);
return Optional.of(schemaTables.get(key));
}
}
String schema = key.getSchema(), table = key.getTable();
boolean changed = false;
if (schemas.containsKey(key.getSchema())) {
schema = schemas.get(key.getSchema());
changed = true;
}
if (tables.containsKey(key.getTable())) {
table = tables.get(key.getTable());
changed = true;
String table = tables.get(key.getTable());
return Optional.of(new SchemaAndTable(key.getSchema(), table));
}
return changed ? new SchemaAndTable(schema, table) : key;
return Optional.absent();
}
public String getColumnOverride(SchemaAndTable key, String column) {
public Optional<String> getColumnOverride(SchemaAndTable key, String column) {
Map<String, String> columnOverrides;
String newColumn = null;
columnOverrides = schemaTableColumns.get(key);
if (columnOverrides != null && (newColumn = columnOverrides.get(column)) != null) {
return newColumn;
return Optional.of(newColumn);
}
columnOverrides = tableColumns.get(key.getTable());
if (columnOverrides != null && (newColumn = columnOverrides.get(column)) != null) {
return newColumn;
return Optional.of(newColumn);
}
return column;
}
public String registerSchemaOverride(String oldSchema, String newSchema) {
return schemas.put(oldSchema, newSchema);
return Optional.absent();
}
public String registerTableOverride(String oldTable, String newTable) {

View File

@ -0,0 +1,18 @@
/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* 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.
*/
/**
* Changing database identifier names in serialized SQL queries.
*/
package com.querydsl.sql.namemapping;

View File

@ -26,7 +26,13 @@ import org.junit.Test;
import com.querydsl.core.alias.Gender;
import com.querydsl.sql.domain.QSurvey;
import com.querydsl.sql.types.*;
import com.querydsl.sql.namemapping.ChangeCaseNameMapping;
import com.querydsl.sql.namemapping.ChangeCaseNameMapping.LetterCase;
import com.querydsl.sql.types.EnumByNameType;
import com.querydsl.sql.types.InputStreamType;
import com.querydsl.sql.types.Null;
import com.querydsl.sql.types.StringType;
import com.querydsl.sql.types.UtilDateType;
public class ConfigurationTest {
@ -68,9 +74,16 @@ public class ConfigurationTest {
assertEquals("pub", configuration.getOverride(new SchemaAndTable("public", "")).getSchema());
assertEquals("emp", configuration.getOverride(new SchemaAndTable("", "employee")).getTable());
assertEquals("employees", configuration.getOverride(new SchemaAndTable("public", "employee")).getTable());
// assertEquals("pub", configuration.getSchema("public"));
// assertEquals("emp", configuration.getTable("", "employee"));
// assertEquals("employees", configuration.getTable("public", "employee"));
configuration.setDynamicNameMapping(new ChangeCaseNameMapping(LetterCase.UPPER));
String notDirectOverriden = "notDirectOverriden";
assertEquals(notDirectOverriden.toUpperCase(),
configuration.getOverride(new SchemaAndTable("public", notDirectOverriden)).getTable());
// assertEquals("pub", configuration.getSchema("public"));
// assertEquals("emp", configuration.getTable("", "employee"));
// assertEquals("employees", configuration.getTable("public",
// "employee"));
}
@Test