diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/Configuration.java b/querydsl-sql/src/main/java/com/querydsl/sql/Configuration.java index 16d765d9c..8b774d6fe 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/Configuration.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/Configuration.java @@ -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 schemaMapping = Maps.newHashMap(); private final Map> 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 + * register*Override 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); } /** diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/ChainedNameMapping.java b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/ChainedNameMapping.java new file mode 100644 index 000000000..65c015088 --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/ChainedNameMapping.java @@ -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 getColumnOverride(SchemaAndTable key, String column) { + for (NameMapping nameMapping : nameMappings) { + Optional overriddenColumnName = nameMapping.getColumnOverride(key, column); + if (overriddenColumnName.isPresent()) { + return overriddenColumnName; + } + } + return Optional.absent(); + } + + @Override + public Optional getOverride(SchemaAndTable key) { + for (NameMapping nameMapping : nameMappings) { + Optional overridden = nameMapping.getOverride(key); + if (overridden.isPresent()) { + return overridden; + } + } + return Optional.absent(); + } + +} diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/ChangeCaseNameMapping.java b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/ChangeCaseNameMapping.java new file mode 100644 index 000000000..46fca91ef --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/ChangeCaseNameMapping.java @@ -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 stores*Identifiers 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 getColumnOverride(SchemaAndTable key, String column) { + return Optional.of(column.toUpperCase()); + } + + @Override + public Optional 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(); + } + } + +} diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/NameMapping.java b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/NameMapping.java new file mode 100644 index 000000000..2b672a6f5 --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/NameMapping.java @@ -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 getColumnOverride(SchemaAndTable key, String column); + + Optional getOverride(SchemaAndTable key); + +} diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/NameMapping.java b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/PreConfiguredNameMapping.java similarity index 75% rename from querydsl-sql/src/main/java/com/querydsl/sql/NameMapping.java rename to querydsl-sql/src/main/java/com/querydsl/sql/namemapping/PreConfiguredNameMapping.java index 9143e705f..83c8dae1e 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/NameMapping.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/PreConfiguredNameMapping.java @@ -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 schemaTables = Maps.newHashMap(); - private final Map schemas = Maps.newHashMap(); - private final Map tables = Maps.newHashMap(); private final Map> schemaTableColumns = Maps.newHashMap(); private final Map> tableColumns = Maps.newHashMap(); - public SchemaAndTable getOverride(SchemaAndTable key) { + public Optional 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 getColumnOverride(SchemaAndTable key, String column) { Map 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) { diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/package-info.java b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/package-info.java new file mode 100644 index 000000000..2a833aaf9 --- /dev/null +++ b/querydsl-sql/src/main/java/com/querydsl/sql/namemapping/package-info.java @@ -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; diff --git a/querydsl-sql/src/test/java/com/querydsl/sql/ConfigurationTest.java b/querydsl-sql/src/test/java/com/querydsl/sql/ConfigurationTest.java index 27ac509a8..5e4a45097 100644 --- a/querydsl-sql/src/test/java/com/querydsl/sql/ConfigurationTest.java +++ b/querydsl-sql/src/test/java/com/querydsl/sql/ConfigurationTest.java @@ -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