Skip to content
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ target
derby.log
.metadata
bin/

.idea
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.Procedure;
import org.apache.cayenne.map.ProcedureParameter;
import org.apache.cayenne.map.naming.BasicNamingStrategy;
import org.apache.cayenne.map.naming.BasicNameGenerator;
import org.apache.cayenne.map.naming.ExportedKey;
import org.apache.cayenne.map.naming.NamingStrategy;
import org.apache.cayenne.map.naming.ObjectNameGenerator;
import org.apache.cayenne.util.EntityMergeSupport;
import org.apache.cayenne.util.Util;
import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -106,26 +106,26 @@ private static String uniqueRelName(Entity entity, String preferredName) {
/**
* Strategy for choosing names for entities, attributes and relationships
*/
protected NamingStrategy namingStrategy;
protected ObjectNameGenerator nameGenerator;

/**
* Creates new DbLoader.
*/
public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate) {
this(connection, adapter, delegate, new BasicNamingStrategy());
this(connection, adapter, delegate, new BasicNameGenerator());
}

/**
* Creates new DbLoader with specified naming strategy.
*
* @since 3.0
*/
public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate, NamingStrategy strategy) {
public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate, ObjectNameGenerator strategy) {
this.adapter = adapter;
this.connection = connection;
this.delegate = delegate;

setNamingStrategy(strategy);
setNameGenerator(strategy);
}

/**
Expand Down Expand Up @@ -526,7 +526,7 @@ public void loadObjEntities(DataMap map) {
continue;
}

String objEntityName = namingStrategy.createObjEntityName(dbEntity);
String objEntityName = nameGenerator.createObjEntityName(dbEntity);
// this loop will terminate even if no valid name is found
// to prevent loader from looping forever (though such case is very
// unlikely)
Expand All @@ -553,7 +553,7 @@ public void loadObjEntities(DataMap map) {
* @since 3.2
*/
protected EntityMergeSupport createEntityMerger(DataMap map) {
return new EntityMergeSupport(map, namingStrategy, !creatingMeaningfulPK);
return new EntityMergeSupport(map, nameGenerator, !creatingMeaningfulPK);
}

/** Loads database relationships into a DataMap. */
Expand Down Expand Up @@ -621,14 +621,14 @@ private void loadDbRelationships(DbEntity pkEntity, DataMap map) throws SQLExcep
continue;
} else {
// init relationship
String forwardPreferredName = namingStrategy.createDbRelationshipName(key, true);
String forwardPreferredName = nameGenerator.createDbRelationshipName(key, true);
forwardRelationship = new DbRelationship(uniqueRelName(pkEntity, forwardPreferredName));

forwardRelationship.setSourceEntity(pkEntity);
forwardRelationship.setTargetEntity(fkEntity);
pkEntity.addRelationship(forwardRelationship);

String reversePreferredName = namingStrategy.createDbRelationshipName(key, false);
String reversePreferredName = nameGenerator.createDbRelationshipName(key, false);
reverseRelationship = new DbRelationshipDetected(uniqueRelName(fkEntity, reversePreferredName));
reverseRelationship.setFkName(fkName);
reverseRelationship.setToMany(false);
Expand Down Expand Up @@ -706,7 +706,7 @@ protected void postprocessMasterDbRelationship(DbRelationship relationship, Expo
if (!toMany) {
Entity source = relationship.getSourceEntity();
source.removeRelationship(relationship.getName());
relationship.setName(DbLoader.uniqueRelName(source, namingStrategy.createDbRelationshipName(key, false)));
relationship.setName(DbLoader.uniqueRelName(source, nameGenerator.createDbRelationshipName(key, false)));
source.addRelationship(relationship);
}

Expand All @@ -721,10 +721,10 @@ private void flattenManyToManyRelationships(DataMap map) {
List<ObjEntity> entitiesForDelete = new ArrayList<ObjEntity>();

for (ObjEntity curEntity : map.getObjEntities()) {
ManyToManyCandidateEntity entity = new ManyToManyCandidateEntity(curEntity);
ManyToManyCandidateEntity entity = ManyToManyCandidateEntity.build(curEntity);

if (entity.isRepresentManyToManyTable()) {
entity.optimizeRelationships();
if (entity != null) {
entity.optimizeRelationships(getNameGenerator());
entitiesForDelete.add(curEntity);
}
}
Expand Down Expand Up @@ -1009,20 +1009,20 @@ public void loadProcedures(DataMap dataMap, String catalogPattern, String schema
*
* @since 3.0
*/
public void setNamingStrategy(NamingStrategy strategy) {
public void setNameGenerator(ObjectNameGenerator strategy) {
// null values are not allowed
if (strategy == null) {
throw new NullPointerException("Null strategy not allowed");
}

this.namingStrategy = strategy;
this.nameGenerator = strategy;
}

/**
* @return naming strategy for reverse engineering
* @since 3.0
*/
public NamingStrategy getNamingStrategy() {
return namingStrategy;
public ObjectNameGenerator getNameGenerator() {
return nameGenerator;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,107 +24,103 @@
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
import org.apache.cayenne.util.NamedObjectFactory;
import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
import org.apache.cayenne.map.naming.ExportedKey;
import org.apache.cayenne.map.naming.NameCheckers;
import org.apache.cayenne.map.naming.ObjectNameGenerator;

/**
* Class represent ObjEntity that may be optimized using flattened relationships
* as many to many table
*/
class ManyToManyCandidateEntity {
private ObjEntity entity;
private final ObjEntity joinEntity;

public ManyToManyCandidateEntity(ObjEntity entityValue) {
entity = entityValue;
}
private final DbRelationship dbRel1;
private final DbRelationship dbRel2;

public ObjEntity getEntity() {
return entity;
}
private final ObjEntity entity1;
private final ObjEntity entity2;

private boolean isTargetEntitiesDifferent() {
return !getTargetEntity1().equals(getTargetEntity2());
}
private final DbRelationship reverseRelationship1;
private final DbRelationship reverseRelationship2;

private boolean isRelationshipsHasDependentPK() {
boolean isRelationship1HasDepPK = getDbRelationship1().getReverseRelationship().isToDependentPK();
boolean isRelationship2HasDepPK = getDbRelationship2().getReverseRelationship().isToDependentPK();
private ManyToManyCandidateEntity(ObjEntity entityValue, List<ObjRelationship> relationships) {
joinEntity = entityValue;

return isRelationship1HasDepPK && isRelationship2HasDepPK;
}
ObjRelationship rel1 = relationships.get(0);
ObjRelationship rel2 = relationships.get(1);

private ObjRelationship getRelationship1() {
List<ObjRelationship> relationships = new ArrayList<ObjRelationship>(entity.getRelationships());
return relationships.get(0);
}
dbRel1 = rel1.getDbRelationships().get(0);
dbRel2 = rel2.getDbRelationships().get(0);

private ObjRelationship getRelationship2() {
List<ObjRelationship> relationships = new ArrayList<ObjRelationship>(entity.getRelationships());
return relationships.get(1);
}
reverseRelationship1 = dbRel1.getReverseRelationship();
reverseRelationship2 = dbRel2.getReverseRelationship();

private ObjEntity getTargetEntity1() {
return (ObjEntity) getRelationship1().getTargetEntity();
}

private ObjEntity getTargetEntity2() {
return (ObjEntity) getRelationship2().getTargetEntity();
}

private DbRelationship getDbRelationship1() {
return getRelationship1().getDbRelationships().get(0);
}

private DbRelationship getDbRelationship2() {
return getRelationship2().getDbRelationships().get(0);
entity1 = rel1.getTargetEntity();
entity2 = rel2.getTargetEntity();
}

/**
* Method check - if current entity represent many to many temporary table
* @return true if current entity is represent many to many table; otherwise returns false
*/
public boolean isRepresentManyToManyTable() {
boolean hasTwoRelationships = entity.getRelationships().size() == 2;
boolean isNotHaveAttributes = entity.getAttributes().size() == 0;
public static ManyToManyCandidateEntity build(ObjEntity joinEntity) {
ArrayList<ObjRelationship> relationships = new ArrayList<ObjRelationship>(joinEntity.getRelationships());
if (relationships.size() != 2) {
return null;
}

return hasTwoRelationships && isNotHaveAttributes && isRelationshipsHasDependentPK()
&& isTargetEntitiesDifferent();
ManyToManyCandidateEntity candidateEntity = new ManyToManyCandidateEntity(joinEntity, relationships);
if (candidateEntity.isManyToMany()) {
return candidateEntity;
}

return null;
}

private void removeRelationshipsFromTargetEntities() {
getTargetEntity1().removeRelationship(getRelationship1().getReverseRelationship().getName());
getTargetEntity2().removeRelationship(getRelationship2().getReverseRelationship().getName());
private boolean isManyToMany() {
boolean isNotHaveAttributes = joinEntity.getAttributes().size() == 0;

return isNotHaveAttributes && reverseRelationship1.isToDependentPK() && reverseRelationship2.isToDependentPK()
&& !entity1.equals(entity2);
}

private void addFlattenedRelationship(ObjEntity srcEntity, ObjEntity dstEntity,
DbRelationship... relationshipPath) {
ObjRelationship newRelationship = (ObjRelationship) NamedObjectFactory.createRelationship(srcEntity, dstEntity,
true);
private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity,
DbRelationship rel1, DbRelationship rel2) {

ExportedKey key = new ExportedKey(rel1.getSourceEntity().getName(),
rel1.getSourceAttributes().iterator().next().getName(),
null,
rel2.getTargetEntity().getName(),
rel2.getTargetAttributes().iterator().next().getName(),
null);

ObjRelationship newRelationship = new ObjRelationship();
newRelationship.setName(DefaultUniqueNameGenerator.generate(NameCheckers.ObjRelationship, srcEntity,
nameGenerator.createDbRelationshipName(key, true)));

newRelationship.setSourceEntity(srcEntity);
newRelationship.setTargetEntity(dstEntity);

for (DbRelationship curRelationship : relationshipPath) {
newRelationship.addDbRelationship(curRelationship);
}
newRelationship.addDbRelationship(rel1);
newRelationship.addDbRelationship(rel2);

srcEntity.addRelationship(newRelationship);
}

/**
* Method make direct relationships between 2 entities and remove relationships to
* many to many entity
*
* @param nameGenerator
*/
public void optimizeRelationships() {
removeRelationshipsFromTargetEntities();

DbRelationship dbRelationship1 = getRelationship1().getDbRelationships().get(0);
DbRelationship dbRelationship2 = getRelationship2().getDbRelationships().get(0);

addFlattenedRelationship(getTargetEntity1(), getTargetEntity2(), dbRelationship1.getReverseRelationship(),
dbRelationship2);
public void optimizeRelationships(ObjectNameGenerator nameGenerator) {
entity1.removeRelationship(reverseRelationship1.getName());
entity2.removeRelationship(reverseRelationship2.getName());

addFlattenedRelationship(getTargetEntity2(), getTargetEntity1(), dbRelationship2.getReverseRelationship(),
dbRelationship1);
addFlattenedRelationship(nameGenerator, entity1, entity2, reverseRelationship1, dbRel2);
addFlattenedRelationship(nameGenerator, entity2, entity1, reverseRelationship2, dbRel1);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,9 @@ public void encodeAsXML(XMLEncoder encoder) {
* present.
*/
public String getFullyQualifiedName() {

if (catalog != null) {
return (schema != null) ? catalog + '.' + schema + '.' + name : catalog + '.' + name;
} else {
return (schema != null) ? schema + '.' + name : name;
}
return (catalog != null ? catalog + '.' : "")
+ (schema != null ? schema + '.' : "")
+ name;
}

/**
Expand Down
21 changes: 10 additions & 11 deletions cayenne-server/src/main/java/org/apache/cayenne/map/ObjEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,7 @@

package org.apache.cayenne.map;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.*;

import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.configuration.ConfigurationNode;
Expand All @@ -41,7 +32,7 @@
import org.apache.cayenne.map.event.EntityEvent;
import org.apache.cayenne.map.event.ObjEntityListener;
import org.apache.cayenne.util.CayenneMapEntry;
import org.apache.cayenne.util.NameConverter;
import org.apache.cayenne.map.naming.NameConverter;
import org.apache.cayenne.util.Util;
import org.apache.cayenne.util.XMLEncoder;
import org.apache.commons.collections.Transformer;
Expand Down Expand Up @@ -1115,6 +1106,14 @@ private PathComponentIterator createPathIterator(String path) {
// here?
}

public Set<String> getCallbackMethods() {
Set<String> res = new LinkedHashSet<String>();
for (CallbackDescriptor descriptor : getCallbackMap().getCallbacks()) {
res.addAll(descriptor.getCallbackMethods());
}
return res;
}

final class DBPathConverter implements Transformer {

// TODO: make it a public method - resolveDBPathComponents or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.util.NameConverter;

/**
* BasicNamingStrategy is an naming strategy that creates names in Cayenne's
* old-fashioned manner, i.e. the same way Cayenne did before 3.0
*
* @since 3.0
*/
public class BasicNamingStrategy implements NamingStrategy {
public class BasicNameGenerator implements ObjectNameGenerator {
public String createDbRelationshipName(
ExportedKey key,
boolean toMany) {
Expand Down
Loading