for (PersistentProperty field : ai.getPersistentProperties()) {
Object ob = field.getProperty(o);
String columnName = field.getColumnName();
if (ob == null) {
attsToDelete.add(new Attribute(columnName, null));
continue;
}
if (field.isForeignKeyRelationship()) {
// store the id of this object
if (Collection.class.isAssignableFrom(field.getRawClass())) {
for (Object each : (Collection) ob) {
String id2 = em.getId(each);
attsToPut.add(new ReplaceableAttribute(columnName, id2, true));
}
} else {
String id2 = em.getId(ob);
attsToPut.add(new ReplaceableAttribute(columnName, id2, true));
/* check if we should persist this */
boolean persistRelationship = false;
ManyToOne a = field.getGetter().getAnnotation(ManyToOne.class);
if (a != null && null != a.cascade()) {
CascadeType[] cascadeType = a.cascade();
for (CascadeType type : cascadeType) {
if (CascadeType.ALL == type || CascadeType.PERSIST == type) {
persistRelationship = true;
}
}
}
if (persistRelationship) {
em.persist(ob);
}
}
} else if (field.isVersioned()) {
Long curVersion = Long.parseLong("" + ob);
nextVersion = (1 + curVersion);
attsToPut.add(new ReplaceableAttribute(columnName, em.padOrConvertIfRequired(nextVersion), true));
if (curVersion > 0) {
expected = new UpdateCondition(columnName, em.padOrConvertIfRequired(curVersion), true);
} else {
expected = new UpdateCondition().withName(columnName).withExists(false);
}
versionField = field;
} else if (field.isInverseRelationship()) {
// FORCING BI-DIRECTIONAL RIGHT NOW SO JUST IGNORE
// ... except for cascading persistence down to all items in the
// OneToMany collection
/* check if we should persist this */
boolean persistRelationship = false;
OneToMany a = field.getGetter().getAnnotation(OneToMany.class);
CascadeType[] cascadeType = a.cascade();
for (CascadeType type : cascadeType) {
if (CascadeType.ALL == type || CascadeType.PERSIST == type) {
persistRelationship = true;
}
}
if (persistRelationship) {
if (ob instanceof Collection) {
// it's OneToMany, so this should always be the case,
// shouldn't it?
for (Object _item : (Collection) ob) {
// persist each item in the collection
em.persist(_item);
}
}
}
} else if (field.isLob()) {
// store in s3
AmazonS3 s3 = null;
// todo: need to make sure we only store to S3 if it's changed,
// too slow.
logger.fine("putting lob to s3");
long start3 = System.currentTimeMillis();
s3 = em.getS3Service();
String bucketName = em.getS3BucketName();
String s3ObjectId = id + "-" + field.getFieldName();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(ob);
byte[] contentBytes = bos.toByteArray();
out.close();
InputStream input = new ByteArrayInputStream(contentBytes);
s3.putObject(bucketName, s3ObjectId, input, null);
em.statsS3Put(System.currentTimeMillis() - start3);
logger.finer("setting lobkeyattribute=" + columnName + " - " + s3ObjectId);
attsToPut.add(new ReplaceableAttribute(columnName, s3ObjectId, true));
} else if (field.getEnumType() != null) {
String toSet = getEnumValue(field, o);
attsToPut.add(new ReplaceableAttribute(columnName, toSet, true));
} else if (field.isId()) {
continue;
} else if (Collection.class.isInstance(ob)) {
for (Object each : ((Collection) ob)) {
String toSet = each != null ? em.padOrConvertIfRequired(each) : "";
// todo: throw an exception if this is going to exceed
// maximum size, suggest using @Lob
attsToPut.add(new ReplaceableAttribute(columnName, toSet, true));
}
} else {
String toSet = ob != null ? em.padOrConvertIfRequired(ob) : "";
// todo: throw an exception if this is going to exceed maximum
// size, suggest using @Lob
attsToPut.add(new ReplaceableAttribute(columnName, toSet, true));
}
}
// Now finally send it for storage (If have attributes to add)
long start2 = System.currentTimeMillis();
long duration2;
if (!attsToPut.isEmpty()) {
this.em.getSimpleDb().putAttributes(
new PutAttributesRequest().withDomainName(domainName).withItemName(id).withAttributes(attsToPut)
.withExpected(expected));
duration2 = System.currentTimeMillis() - start2;
if (logger.isLoggable(Level.FINE))
logger.fine("putAttributes time=" + (duration2));
em.statsAttsPut(attsToPut.size(), duration2);
if (null != versionField)
versionField.setProperty(o, nextVersion);
}
/*
* Check for nulled attributes so we can send a delete call. Don't
* delete attributes if this is a new object AND don't delete atts if
* it's not dirty AND don't delete if no nulls were set (nulledField on
* LazyInterceptor)
*/
if (interceptor != null) {
if (interceptor.getNulledFields() != null && interceptor.getNulledFields().size() > 0) {
List<Attribute> attsToDelete2 = new ArrayList<Attribute>();
for (String s : interceptor.getNulledFields().keySet()) {
String columnName = ai.getPersistentProperty(s).getColumnName();
attsToDelete2.add(new Attribute(columnName, null));
}
start2 = System.currentTimeMillis();
this.em.getSimpleDb().deleteAttributes(
new DeleteAttributesRequest().withDomainName(domainName).withItemName(id)
.withAttributes(attsToDelete2));