Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CAY-2639 DBImport and DB name case sensitivity. Feature for choosing case-sensitive naming. #496

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class DbImporterTask extends Task {
public DbImporterTask() {
this.config = new DbImportConfiguration();
this.config.setUsePrimitives(true);
this.config.setUseCaseSensitiveNaming(false);
this.config.setUseJava7Types(false);
this.config.setNamingStrategy(DefaultObjectNameGenerator.class.getName());

Expand Down Expand Up @@ -247,6 +248,13 @@ public void setUsePrimitives(boolean flag) {
config.setUsePrimitives(flag);
}

/**
* @since 4.2
*/
public void setUseCaseSensitiveNaming(boolean flag) {
config.setUseCaseSensitiveNaming(flag);
}

/**
* @since 4.0
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,14 +364,20 @@ private void validateAttributes() {
* the "encoding" property.
*/
protected Writer openWriter(TemplateType templateType) throws Exception {

File outFile = (templateType.isSuperclass()) ? fileForSuperclass() : fileForClass();
boolean isSuperclass = templateType.isSuperclass();
File outFile = (isSuperclass) ? fileForSuperclass() : fileForClass();
if (outFile == null) {
return null;
}

if (isSuperclass && outFile.exists() && fileNeedUpdate(outFile, cgenConfiguration.getSuperTemplate())) {
if (!outFile.delete()) {
logger.warn("File " + outFile.getAbsolutePath() + " can't be deleted.");
}
}

if (logger != null) {
String label = templateType.isSuperclass() ? "superclass" : "class";
String label = isSuperclass ? "superclass" : "class";
logger.info("Generating " + label + " file: " + outFile.getCanonicalPath());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.apache.cayenne.gen;

import java.io.*;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -333,4 +334,30 @@ public void testFileForClass() throws Exception {
cgenConfiguration.setOverwrite(true);
assertNull(action.openWriter(templateType));
}

@Test
public void testDeleteFileIfChanged() throws Exception {

TemplateType templateType = TemplateType.DATAMAP_SUPERCLASS;
String rootFolder = tempFolder.getRoot().getAbsolutePath();

File outFile = new File(rootFolder + "/_TestCLASS2.java");
assertTrue(outFile.createNewFile());

cgenConfiguration.setSuperTemplate(outFile.getAbsolutePath());
cgenConfiguration.setRootPath(Paths.get(rootFolder));
cgenConfiguration.setRelPath(".");
action = new ClassGenerationAction(cgenConfiguration);
ObjEntity testEntity1 = new ObjEntity("TEST");
testEntity1.setSuperClassName("_TestClass2");

action.context.put(Artifact.SUPER_PACKAGE_KEY, "");
action.context.put(Artifact.SUPER_CLASS_KEY, "_TestClass2");
try (Writer out = action.openWriter(templateType);){
assertNotNull(out);
}
outFile = new File(rootFolder + "/_TestClass2.java");
assertTrue(outFile.exists());
assertEquals(outFile.getAbsolutePath(), rootFolder + File.separator + "_TestClass2.java");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.cayenne.dba.oracle.Oracle8Adapter;
import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.dba.postgres.PostgresAdapter;
import org.apache.cayenne.dba.sqlite.SQLiteAdapter;
import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
import org.apache.cayenne.dba.sybase.SybaseAdapter;
import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
Expand All @@ -46,6 +47,7 @@
import org.apache.cayenne.dbsync.merge.factory.OracleMergerTokenFactory;
import org.apache.cayenne.dbsync.merge.factory.PostgresMergerTokenFactory;
import org.apache.cayenne.dbsync.merge.factory.SQLServerMergerTokenFactory;
import org.apache.cayenne.dbsync.merge.factory.SQLiteMergerTokenFactory;
import org.apache.cayenne.dbsync.merge.factory.SybaseMergerTokenFactory;
import org.apache.cayenne.di.Binder;
import org.apache.cayenne.di.MapBuilder;
Expand Down Expand Up @@ -84,7 +86,8 @@ public void configure(Binder binder) {
.put(Oracle8Adapter.class.getName(), OracleMergerTokenFactory.class)
.put(PostgresAdapter.class.getName(), PostgresMergerTokenFactory.class)
.put(SQLServerAdapter.class.getName(), SQLServerMergerTokenFactory.class)
.put(SybaseAdapter.class.getName(), SybaseMergerTokenFactory.class);
.put(SybaseAdapter.class.getName(), SybaseMergerTokenFactory.class)
.put(SQLiteAdapter.class.getName(), SQLiteMergerTokenFactory.class);

binder.bind(MergerTokenFactoryProvider.class).to(MergerTokenFactoryProvider.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,37 @@

import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
import org.apache.cayenne.dbsync.merge.token.MergerToken;
import org.apache.cayenne.map.DataMap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;

abstract class AbstractMerger<T, M> implements Merger<T> {

private MergerDictionaryDiff<M> diff;
private MergerTokenFactory tokenFactory;
private DbEntityDictionary originalDictionary;
private Function<String, String> nameConverter;

AbstractMerger(MergerTokenFactory tokenFactory) {
AbstractMerger(MergerTokenFactory tokenFactory, Function<String, String> nameConverter) {
this.tokenFactory = tokenFactory;
this.nameConverter = nameConverter;
}

/**
* @since 4.2
* Sets function for converting string for naming.
*/
public void setNameConverter(Function<String, String> nameConverter) {
this.nameConverter = nameConverter;
}

/**
* @since 4.2
*/
public Function<String, String> getNameConverter() {
return nameConverter;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
import org.apache.cayenne.dbsync.merge.token.MergerToken;
import org.apache.cayenne.map.DataMap;

class ChainMerger<T, M> extends AbstractMerger<T, M> {

Expand All @@ -33,7 +32,7 @@ class ChainMerger<T, M> extends AbstractMerger<T, M> {
private final AbstractMerger<?, T> parentMerger;

ChainMerger(MergerTokenFactory tokenFactory, AbstractMerger<T, M> merger, AbstractMerger<?, T> parentMerger) {
super(tokenFactory);
super(tokenFactory, merger.getNameConverter());
this.merger = merger;
this.parentMerger = parentMerger;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
import org.apache.cayenne.dbsync.merge.token.EmptyValueForNullProvider;
Expand All @@ -48,6 +49,7 @@ public class DataMapMerger implements Merger<DataMap> {
private FiltersConfig filters;
private DbEntityMerger dbEntityMerger;
private List<AbstractMerger<?, ?>> mergerList = new ArrayList<>();
private Function<String, String> nameConverter;

private DataMapMerger() {
}
Expand Down Expand Up @@ -81,14 +83,14 @@ private List<MergerToken> createTokens() {
}

private void createDbEntityMerger(DataMap original, DataMap imported) {
dbEntityMerger = new DbEntityMerger(tokenFactory, original, imported, filters, skipPKTokens);
dbEntityMerger = new DbEntityMerger(tokenFactory, original, imported, filters, skipPKTokens, nameConverter);
mergerList.add(dbEntityMerger);
}

private void createAttributeMerger() {
ChainMerger<DbEntity, DbAttribute> dbAttributeMerger = new ChainMerger<>(
tokenFactory,
new DbAttributeMerger(tokenFactory, valueForNull),
new DbAttributeMerger(tokenFactory, valueForNull, nameConverter),
dbEntityMerger
);
mergerList.add(dbAttributeMerger);
Expand All @@ -97,25 +99,21 @@ private void createAttributeMerger() {
private void createRelationshipMerger() {
ChainMerger<DbEntity, DbRelationship> dbRelationshipMerger = new ChainMerger<>(
tokenFactory,
new DbRelationshipMerger(tokenFactory, skipRelationshipsTokens, filters),
new DbRelationshipMerger(tokenFactory, skipRelationshipsTokens, filters, nameConverter),
dbEntityMerger
);
mergerList.add(dbRelationshipMerger);
}

private void createProcedureMerger(DataMap original, DataMap imported) {
ProcedureMerger procedureMerger = new ProcedureMerger(tokenFactory, original, imported, filters);
ProcedureMerger procedureMerger = new ProcedureMerger(tokenFactory, original, imported, filters, nameConverter);
mergerList.add(procedureMerger);
}

public static Builder builder(MergerTokenFactory tokenFactory) {
return new Builder(tokenFactory);
}

public static DataMapMerger build(MergerTokenFactory tokenFactory) {
return builder(tokenFactory).build();
}

public static class Builder {
private DataMapMerger merger;

Expand Down Expand Up @@ -157,5 +155,13 @@ public Builder filters(FiltersConfig filters) {
merger.filters = Objects.requireNonNull(filters);
return this;
}

/**
* @since 4.2
*/
public Builder nameConverter(Function<String, String> nameConverter) {
merger.nameConverter = Objects.requireNonNull(nameConverter);
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;

import org.apache.cayenne.dbsync.merge.token.ValueForNullProvider;
import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
Expand All @@ -43,8 +44,8 @@ class DbAttributeMerger extends AbstractMerger<DbEntity, DbAttribute> {

private final ValueForNullProvider valueForNull;

DbAttributeMerger(MergerTokenFactory tokenFactory, ValueForNullProvider valueForNull) {
super(tokenFactory);
DbAttributeMerger(MergerTokenFactory tokenFactory, ValueForNullProvider valueForNull, Function<String,String> nameConverter) {
super(tokenFactory, nameConverter);
this.valueForNull = valueForNull;
}

Expand All @@ -53,6 +54,7 @@ MergerDictionaryDiff<DbAttribute> createDiff(DbEntity original, DbEntity importe
return new MergerDictionaryDiff.Builder<DbAttribute>()
.originalDictionary(new DbAttributeDictionary(original))
.importedDictionary(new DbAttributeDictionary(imported))
.nameConverter(getNameConverter())
.build();
}

Expand Down Expand Up @@ -89,7 +91,8 @@ Collection<MergerToken> createTokensForMissingImported(DbAttribute original) {
*/
@Override
Collection<MergerToken> createTokensForMissingOriginal(DbAttribute imported) {
DbEntity originalDbEntity = getOriginalDictionary().getByName(imported.getEntity().getName().toUpperCase());
String name = getNameConverter().apply(imported.getEntity().getName());
DbEntity originalDbEntity = getOriginalDictionary().getByName(name);
return Collections.singleton(getTokenFactory().createDropColumnToDb(originalDbEntity, imported));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@

package org.apache.cayenne.dbsync.merge;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
import org.apache.cayenne.dbsync.merge.token.MergerToken;
Expand All @@ -44,8 +46,8 @@ class DbEntityMerger extends AbstractMerger<DataMap, DbEntity> {
private DataMap importedDataMap;

DbEntityMerger(MergerTokenFactory tokenFactory, DataMap original, DataMap imported,
FiltersConfig filtersConfig, boolean skipPKTokens) {
super(tokenFactory);
FiltersConfig filtersConfig, boolean skipPKTokens, Function<String, String> nameConverter) {
super(tokenFactory, nameConverter);
this.filtersConfig = filtersConfig;
this.skipPKTokens = skipPKTokens;
originalDataMap = original;
Expand All @@ -63,18 +65,26 @@ MergerDictionaryDiff<DbEntity> createDiff(DataMap original, DataMap imported) {
MergerDictionaryDiff<DbEntity> diff = new MergerDictionaryDiff.Builder<DbEntity>()
.originalDictionary(dictionary)
.importedDictionary(new DbEntityDictionary(imported, null))
.nameConverter(getNameConverter())
.build();
setOriginalDictionary(dictionary);
return diff;
}

/**
* Generate Drop Table in DB token
* The creating entity divides into two parts because of the necessity for creating relationships after entity.
* This is caused by an unknown name the target objEntity for the relationship before all entities were created.
* @param imported DbEntity not found in model but found in DB
*/
@Override
Collection<MergerToken> createTokensForMissingOriginal(DbEntity imported) {
return Collections.singleton(getTokenFactory().createDropTableToDb(imported));
Collection<MergerToken> tokens = new ArrayList<>();
tokens.add(getTokenFactory().createDropTableToDb(imported));
for (DbRelationship rel : imported.getRelationships()) {
tokens.add(getTokenFactory().createDropRelationshipToDb(imported, rel));
}
return tokens;
}

/**
Expand Down Expand Up @@ -118,21 +128,21 @@ private Collection<MergerToken> checkPrimaryKeyChange(DbEntity original, DbEntit
primaryKeyName = ((DetectedDbEntity) imported).getPrimaryKeyName();
}

if (upperCaseEntityNames(primaryKeyOriginal).equals(upperCaseEntityNames(primaryKeyNew))) {
if (convertNames(primaryKeyOriginal).equals(convertNames(primaryKeyNew))) {
return null;
}

return Collections.singleton(
getTokenFactory().createSetPrimaryKeyToDb(
original, primaryKeyOriginal, primaryKeyNew, primaryKeyName
original, primaryKeyOriginal, primaryKeyNew, primaryKeyName, getNameConverter()
)
);
}

private Set<String> upperCaseEntityNames(Collection<? extends Attribute> attributes) {
private Set<String> convertNames(Collection<? extends Attribute> attributes) {
Set<String> names = new HashSet<>();
for (Attribute attr : attributes) {
names.add(attr.getName().toUpperCase());
names.add(getNameConverter().apply(attr.getName()));
}
return names;
}
Expand Down
Loading