use of org.apache.cayenne.map.ObjAttribute in project cayenne by apache.
the class BaseDataObject method validateForSave.
/**
* Performs property validation of the object, appending any validation
* failures to the provided validationResult object. This method is invoked
* from "validateFor.." before committing a NEW or MODIFIED object to the
* database. Validation includes checking for null values and value sizes.
* CayenneDataObject subclasses may override this method, calling super.
*
* @since 1.1
*/
protected void validateForSave(ValidationResult validationResult) {
ObjEntity objEntity = getObjectContext().getEntityResolver().getObjEntity(this);
if (objEntity == null) {
throw new CayenneRuntimeException("No ObjEntity mapping found for DataObject %s", getClass().getName());
}
// validate mandatory attributes
Map<String, ValidationFailure> failedDbAttributes = null;
for (ObjAttribute next : objEntity.getAttributes()) {
// TODO: andrus, 2/20/2007 - handle embedded attribute
if (next instanceof EmbeddedAttribute) {
continue;
}
DbAttribute dbAttribute = next.getDbAttribute();
if (dbAttribute == null) {
throw new CayenneRuntimeException("ObjAttribute '%s" + "' does not have a corresponding DbAttribute", next.getName());
}
// pk may still be generated
if (dbAttribute.isPrimaryKey()) {
continue;
}
Object value = this.readPropertyDirectly(next.getName());
if (dbAttribute.isMandatory()) {
ValidationFailure failure = BeanValidationFailure.validateNotNull(this, next.getName(), value);
if (failure != null) {
if (failedDbAttributes == null) {
failedDbAttributes = new HashMap<>();
}
failedDbAttributes.put(dbAttribute.getName(), failure);
continue;
}
}
// validate length
if (value != null && dbAttribute.getMaxLength() > 0) {
if (value.getClass().isArray()) {
int len = Array.getLength(value);
if (len > dbAttribute.getMaxLength()) {
String message = "\"" + next.getName() + "\" exceeds maximum allowed length (" + dbAttribute.getMaxLength() + " bytes): " + len;
validationResult.addFailure(new BeanValidationFailure(this, next.getName(), message));
}
} else if (value instanceof CharSequence) {
int len = ((CharSequence) value).length();
if (len > dbAttribute.getMaxLength()) {
String message = "\"" + next.getName() + "\" exceeds maximum allowed length (" + dbAttribute.getMaxLength() + " chars): " + len;
validationResult.addFailure(new BeanValidationFailure(this, next.getName(), message));
}
}
}
}
// validate mandatory relationships
for (final ObjRelationship relationship : objEntity.getRelationships()) {
List<DbRelationship> dbRels = relationship.getDbRelationships();
if (dbRels.isEmpty()) {
continue;
}
// see ObjRelationship.recalculateReadOnlyValue() for more info
if (relationship.isSourceIndependentFromTargetChange()) {
continue;
}
// if db relationship is not based on a PK and is based on mandatory
// attributes, see if we have a target object set
// relationship will be validated only if all db path has mandatory
// db relationships
boolean validate = true;
for (DbRelationship dbRelationship : dbRels) {
for (DbJoin join : dbRelationship.getJoins()) {
DbAttribute source = join.getSource();
if (source.isMandatory()) {
// clear attribute failures...
if (failedDbAttributes != null && !failedDbAttributes.isEmpty()) {
failedDbAttributes.remove(source.getName());
}
} else {
// do not validate if the relation is based on
// multiple keys with some that can be nullable.
validate = false;
}
}
}
if (validate) {
Object value = this.readPropertyDirectly(relationship.getName());
ValidationFailure failure = BeanValidationFailure.validateNotNull(this, relationship.getName(), value);
if (failure != null) {
validationResult.addFailure(failure);
}
}
}
// deal with previously found attribute failures...
if (failedDbAttributes != null && !failedDbAttributes.isEmpty()) {
for (ValidationFailure failure : failedDbAttributes.values()) {
validationResult.addFailure(failure);
}
}
}
use of org.apache.cayenne.map.ObjAttribute in project cayenne by apache.
the class DataNodeSyncQualifierDescriptor method reset.
void reset(DbEntityClassDescriptor descriptor) {
attributes = new ArrayList<>(3);
valueTransformers = new ArrayList<>(3);
usingOptimisticLocking = descriptor.getEntity().getLockType() == ObjEntity.LOCK_TYPE_OPTIMISTIC;
// master PK columns
if (descriptor.isMaster()) {
for (final DbAttribute attribute : descriptor.getDbEntity().getPrimaryKeys()) {
attributes.add(attribute);
valueTransformers.add(input -> {
ObjectId id = (ObjectId) input.getNodeId();
return id.getIdSnapshot().get(attribute.getName());
});
}
} else {
// TODO: andrus 12/23/2007 - only one step relationship is supported...
if (descriptor.getPathFromMaster().size() != 1) {
throw new CayenneRuntimeException("Only single step dependent relationships are currently supported. Actual path length: %d", descriptor.getPathFromMaster().size());
}
DbRelationship masterDependentDbRel = descriptor.getPathFromMaster().get(0);
if (masterDependentDbRel != null) {
for (final DbJoin dbAttrPair : masterDependentDbRel.getJoins()) {
DbAttribute dbAttribute = dbAttrPair.getTarget();
if (!attributes.contains(dbAttribute)) {
attributes.add(dbAttribute);
valueTransformers.add(input -> {
ObjectId id = (ObjectId) input.getNodeId();
return id.getIdSnapshot().get(dbAttrPair.getSourceName());
});
}
}
}
}
if (usingOptimisticLocking) {
for (final ObjAttribute attribute : descriptor.getEntity().getAttributes()) {
if (attribute.isUsedForLocking()) {
// only care about first step in a flattened attribute
DbAttribute dbAttribute = (DbAttribute) attribute.getDbPathIterator().next();
// only use qualifier if dbEntities match
if (dbAttribute.getEntity().equals(descriptor.getDbEntity()) && !attributes.contains(dbAttribute)) {
attributes.add(dbAttribute);
valueTransformers.add(input -> input.getSnapshotValue(attribute.getName()));
}
}
}
for (final ObjRelationship relationship : descriptor.getEntity().getRelationships()) {
if (relationship.isUsedForLocking()) {
// only care about the first DbRelationship
DbRelationship dbRelationship = relationship.getDbRelationships().get(0);
for (final DbJoin dbAttrPair : dbRelationship.getJoins()) {
DbAttribute dbAttribute = dbAttrPair.getSource();
// relationship transformers override attribute transformers for meaningful FK's...
// why meaningful FKs can go out of sync is another story (CAY-595)
int index = attributes.indexOf(dbAttribute);
if (index >= 0 && !dbAttribute.isForeignKey()) {
continue;
}
Function<ObjectDiff, Object> transformer = input -> {
ObjectId targetId = input.getArcSnapshotValue(relationship.getName());
return targetId != null ? targetId.getIdSnapshot().get(dbAttrPair.getTargetName()) : null;
};
if (index < 0) {
attributes.add(dbAttribute);
valueTransformers.add(transformer);
} else {
valueTransformers.set(index, transformer);
}
}
}
}
}
}
use of org.apache.cayenne.map.ObjAttribute in project cayenne by apache.
the class DataRowUtils method refreshObjectWithSnapshot.
/**
* Replaces all object attribute values with snapshot values. Sets object state to
* COMMITTED, unless the snapshot is partial in which case the state is set to HOLLOW
*/
static void refreshObjectWithSnapshot(ClassDescriptor descriptor, final Persistent object, final DataRow snapshot, final boolean invalidateToManyRelationships) {
final boolean[] isPartialSnapshot = new boolean[1];
descriptor.visitProperties(new PropertyVisitor() {
public boolean visitAttribute(AttributeProperty property) {
ObjAttribute attr = property.getAttribute();
String dbAttrPath = attr.getDbAttributePath();
Object value = snapshot.get(dbAttrPath);
property.writePropertyDirectly(object, null, value);
// checking for the null value first
if (value == null && !snapshot.containsKey(dbAttrPath)) {
isPartialSnapshot[0] = true;
}
return true;
}
public boolean visitToMany(ToManyProperty property) {
// snapshot
if (invalidateToManyRelationships) {
property.invalidate(object);
}
return true;
}
public boolean visitToOne(ToOneProperty property) {
property.invalidate(object);
return true;
}
});
object.setPersistenceState(isPartialSnapshot[0] ? PersistenceState.HOLLOW : PersistenceState.COMMITTED);
}
use of org.apache.cayenne.map.ObjAttribute in project cayenne by apache.
the class PrefetchProcessorJointNode method buildRowMapping.
/**
* Configures row columns mapping for this node entity.
*/
private void buildRowMapping() {
final Map<String, ColumnDescriptor> targetSource = new TreeMap<>();
// build a DB path .. find parent node that terminates the joint group...
PrefetchTreeNode jointRoot = this;
while (jointRoot.getParent() != null && !jointRoot.isDisjointPrefetch() && !jointRoot.isDisjointByIdPrefetch()) {
jointRoot = jointRoot.getParent();
}
final String prefix;
if (jointRoot != this) {
Expression objectPath = ExpressionFactory.exp(getPath(jointRoot));
ASTPath translated = (ASTPath) ((PrefetchProcessorNode) jointRoot).getResolver().getEntity().translateToDbPath(objectPath);
// make sure we do not include "db:" prefix
prefix = translated.getOperand(0) + ".";
} else {
prefix = "";
}
if (getParent() != null && !getParent().isPhantom() && getIncoming() != null && !getIncoming().getRelationship().isFlattened()) {
DbRelationship r = getIncoming().getRelationship().getDbRelationships().get(0);
for (final DbJoin join : r.getJoins()) {
appendColumn(targetSource, join.getTargetName(), prefix + join.getTargetName());
}
}
ClassDescriptor descriptor = resolver.getDescriptor();
descriptor.visitAllProperties(new PropertyVisitor() {
public boolean visitAttribute(AttributeProperty property) {
String target = property.getAttribute().getDbAttributePath();
appendColumn(targetSource, target, prefix + target);
return true;
}
public boolean visitToMany(ToManyProperty property) {
return visitRelationship(property);
}
public boolean visitToOne(ToOneProperty property) {
return visitRelationship(property);
}
private boolean visitRelationship(ArcProperty arc) {
DbRelationship dbRel = arc.getRelationship().getDbRelationships().get(0);
for (DbAttribute attribute : dbRel.getSourceAttributes()) {
String target = attribute.getName();
appendColumn(targetSource, target, prefix + target);
}
return true;
}
});
// append id columns ... (some may have been appended already via relationships)
for (String pkName : descriptor.getEntity().getPrimaryKeyNames()) {
appendColumn(targetSource, pkName, prefix + pkName);
}
// append inheritance discriminator columns...
for (ObjAttribute column : descriptor.getDiscriminatorColumns()) {
String target = column.getDbAttributePath();
appendColumn(targetSource, target, prefix + target);
}
int size = targetSource.size();
this.rowCapacity = (int) Math.ceil(size / 0.75);
this.columns = new ColumnDescriptor[size];
targetSource.values().toArray(columns);
}
use of org.apache.cayenne.map.ObjAttribute in project cayenne by apache.
the class EJBQLIdColumnsTranslator method visitIdentifier.
@Override
public boolean visitIdentifier(EJBQLExpression expression) {
Map<String, String> fields = null;
if (context.isAppendingResultColumns()) {
fields = context.nextEntityResult().getFields();
}
String idVar = expression.getText();
ClassDescriptor descriptor = context.getEntityDescriptor(idVar);
ObjEntity oe = descriptor.getEntity();
for (ObjAttribute oa : oe.getPrimaryKeys()) {
DbAttribute t = oe.getDbEntity().getAttribute(oa.getDbAttributeName());
appendColumn(idVar, oa, t, fields, oa.getType());
}
return false;
}
Aggregations