use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class ObjectDiff method addDiff.
void addDiff(NodeDiff diff, ObjectStore parent) {
boolean addDiff = true;
if (diff instanceof ArcOperation) {
ArcOperation arcDiff = (ArcOperation) diff;
Object targetId = arcDiff.getTargetNodeId();
String arcId = arcDiff.getArcId().toString();
ArcProperty property = (ArcProperty) getClassDescriptor().getProperty(arcId);
if (property == null && arcId.startsWith(ASTDbPath.DB_PREFIX)) {
addPhantomFkDiff(arcDiff);
addDiff = false;
} else if (property instanceof ToManyProperty) {
// record flattened op changes
ObjRelationship relationship = property.getRelationship();
if (relationship.isFlattened()) {
if (flatIds == null) {
flatIds = new HashMap<>();
}
ArcOperation oldOp = flatIds.put(arcDiff, arcDiff);
// "delete" cancels "create" and vice versa...
if (oldOp != null && oldOp.isDelete() != arcDiff.isDelete()) {
addDiff = false;
flatIds.remove(arcDiff);
if (otherDiffs != null) {
otherDiffs.remove(oldOp);
}
}
} else if (property.getComplimentaryReverseArc() == null) {
// register complimentary arc diff
String arc = ASTDbPath.DB_PREFIX + property.getComplimentaryReverseDbRelationshipPath();
ArcOperation complimentartyOp = new ArcOperation(targetId, arcDiff.getNodeId(), arc, arcDiff.isDelete());
parent.registerDiff(targetId, complimentartyOp);
}
} else if (property instanceof ToOneProperty) {
if (currentArcSnapshot == null) {
currentArcSnapshot = new HashMap<>();
}
currentArcSnapshot.put(arcId, targetId);
} else {
String message = (property == null) ? "No property for arcId " + arcId : "Unrecognized property for arcId " + arcId + ": " + property;
throw new CayenneRuntimeException(message);
}
}
if (addDiff) {
if (otherDiffs == null) {
otherDiffs = new ArrayList<>(3);
}
otherDiffs.add(diff);
}
}
use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class EJBQLPathAnaliserTranslator method visitSize.
@Override
public boolean visitSize(EJBQLExpression expression) {
if (expression.getChildrenCount() != 1) {
throw new EJBQLException("SIZE must have exactly one child, got: " + expression.getChildrenCount());
}
if (!(expression.getChild(0) instanceof EJBQLPath)) {
throw new EJBQLException("First child of SIZE must be a collection path, got: " + expression.getChild(1));
}
QuotingStrategy quoter = context.getQuotingStrategy();
EJBQLPath path = (EJBQLPath) expression.getChild(0);
String id = path.getAbsolutePath();
String correlatedEntityId = path.getId();
ClassDescriptor correlatedEntityDescriptor = context.getEntityDescriptor(correlatedEntityId);
String correlatedTableName = quoter.quotedFullyQualifiedName(correlatedEntityDescriptor.getEntity().getDbEntity());
String correlatedTableAlias = context.getTableAlias(correlatedEntityId, correlatedTableName);
String subqueryId = context.createIdAlias(id);
ClassDescriptor targetDescriptor = context.getEntityDescriptor(subqueryId);
if (expression.isNegated()) {
context.append(" NOT");
}
context.append(" EXISTS (SELECT 1 FROM ");
String subqueryTableName = quoter.quotedFullyQualifiedName(targetDescriptor.getEntity().getDbEntity());
String subqueryRootAlias = context.getTableAlias(subqueryId, subqueryTableName);
ObjRelationship relationship = correlatedEntityDescriptor.getEntity().getRelationship(path.getRelativePath());
if (relationship.getDbRelationshipPath().contains(".")) {
// if the DbRelationshipPath contains '.', the relationship is
// flattened
subqueryRootAlias = processFlattenedRelationShip(subqueryRootAlias, relationship);
} else {
// not using "AS" to separate table name and alias name - OpenBase
// doesn't
// support "AS", and the rest of the databases do not care
context.append(subqueryTableName).append(' ').append(subqueryRootAlias);
}
context.append(" WHERE");
DbRelationship correlatedJoinRelationship = context.getIncomingRelationships(new EJBQLTableId(id)).get(0);
Iterator<DbJoin> it = correlatedJoinRelationship.getJoins().iterator();
while (it.hasNext()) {
DbJoin join = it.next();
context.append(' ').append(subqueryRootAlias).append('.').append(join.getTargetName()).append(" = ");
context.append(correlatedTableAlias).append('.').append(quoter.quotedSourceName(join));
if (it.hasNext()) {
context.append(" AND");
}
}
context.append(")");
return false;
}
use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class EJBQLGroupByTranslator method visitPath.
@Override
public boolean visitPath(EJBQLExpression expression, int finishedChildIndex) {
if (itemCount++ > 0) {
context.append(',');
}
EJBQLExpressionVisitor childVisitor = new EJBQLPathTranslator(context) {
@Override
protected void appendMultiColumnPath(EJBQLMultiColumnOperand operand) {
throw new EJBQLException("Can't GROUP BY on multi-column paths or objects");
}
@Override
public boolean visitIdentificationVariable(EJBQLExpression expression) {
String idVariableAbsolutePath = fullPath + "." + expression.getText();
ClassDescriptor descriptor = context.getEntityDescriptor(idVariableAbsolutePath);
if (descriptor != null) {
this.lastAlias = context.getTableAlias(idVariableAbsolutePath, context.getQuotingStrategy().quotedFullyQualifiedName(descriptor.getEntity().getDbEntity()));
}
resolveLastPathComponent(expression.getText());
this.fullPath = fullPath + '.' + lastPathComponent;
return true;
}
@Override
protected void processTerminatingRelationship(ObjRelationship relationship) {
Collection<DbAttribute> dbAttr = ((ObjEntity) relationship.getTargetEntity()).getDbEntity().getAttributes();
DbRelationship dbRelationship = relationship.getDbRelationships().get(0);
DbEntity table = (DbEntity) dbRelationship.getTargetEntity();
Iterator<DbAttribute> it = dbAttr.iterator();
String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath, context.getQuotingStrategy().quotedFullyQualifiedName(table));
boolean first = true;
while (it.hasNext()) {
context.append(!first ? ", " : " ");
DbAttribute dbAttribute = it.next();
context.append(alias).append('.').append(context.getQuotingStrategy().quotedName(dbAttribute));
first = false;
}
}
};
expression.visit(childVisitor);
return false;
}
use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class EJBQLIdentifierColumnsTranslator method visitIdentifier.
@Override
public boolean visitIdentifier(EJBQLExpression expression) {
Map<String, String> xfields = null;
if (context.isAppendingResultColumns()) {
xfields = context.nextEntityResult().getFields();
}
// assign whatever we have to a final ivar so that it can be accessed
// within
// the inner class
final Map<String, String> fields = xfields;
final String idVar = expression.getText();
// append all table columns ... the trick is to follow the algorithm for
// describing the fields in the expression compiler, so that we could
// assign
// columns labels from FieldResults in the order we encounter them
// here...
// TODO: andrus 2008/02/17 - this is a bit of a hack, think of a better
// solution
ClassDescriptor descriptor = context.getEntityDescriptor(idVar);
PropertyVisitor visitor = new PropertyVisitor() {
public boolean visitAttribute(AttributeProperty property) {
ObjAttribute oa = property.getAttribute();
Iterator<?> dbPathIterator = oa.getDbPathIterator();
EJBQLJoinAppender joinAppender = null;
String marker = null;
EJBQLTableId lhsId = new EJBQLTableId(idVar);
while (dbPathIterator.hasNext()) {
Object pathPart = dbPathIterator.next();
if (pathPart == null) {
throw new CayenneRuntimeException("ObjAttribute has no component: %s", oa.getName());
} else if (pathPart instanceof DbRelationship) {
if (marker == null) {
marker = EJBQLJoinAppender.makeJoinTailMarker(idVar);
joinAppender = context.getTranslatorFactory().getJoinAppender(context);
}
DbRelationship dr = (DbRelationship) pathPart;
EJBQLTableId rhsId = new EJBQLTableId(lhsId, dr.getName());
joinAppender.appendOuterJoin(marker, lhsId, rhsId);
lhsId = rhsId;
} else if (pathPart instanceof DbAttribute) {
appendColumn(idVar, oa, (DbAttribute) pathPart, fields, oa.getType());
}
}
return true;
}
public boolean visitToMany(ToManyProperty property) {
visitRelationship(property);
return true;
}
public boolean visitToOne(ToOneProperty property) {
visitRelationship(property);
return true;
}
private void visitRelationship(ArcProperty property) {
ObjRelationship rel = property.getRelationship();
DbRelationship dbRel = rel.getDbRelationships().get(0);
for (DbJoin join : dbRel.getJoins()) {
DbAttribute src = join.getSource();
appendColumn(idVar, null, src, fields);
}
}
};
// EJBQL queries are polymorphic by definition - there is no distinction
// between
// inheritance/no-inheritance fetch
descriptor.visitAllProperties(visitor);
// append id columns ... (some may have been appended already via
// relationships)
DbEntity table = descriptor.getEntity().getDbEntity();
for (DbAttribute pk : table.getPrimaryKeys()) {
appendColumn(idVar, null, pk, fields);
}
// append inheritance discriminator columns...
for (ObjAttribute column : descriptor.getDiscriminatorColumns()) {
appendColumn(idVar, column, column.getDbAttribute(), fields);
}
addPrefetchedColumnsIfAny(idVar);
return false;
}
use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class EJBQLPathTranslator method processLastPathComponent.
protected void processLastPathComponent() {
ObjAttribute attribute = currentEntity.getAttribute(lastPathComponent);
if (attribute != null) {
processTerminatingAttribute(attribute);
return;
}
ObjRelationship relationship = currentEntity.getRelationship(lastPathComponent);
if (relationship != null) {
processTerminatingRelationship(relationship);
return;
}
throw new IllegalStateException("Invalid path component: " + lastPathComponent);
}
Aggregations