runAutoLink = false;
}
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = null;
BaseContentEntity contentEntity;
PublishState oldPublishState = null;
Set<Long> newLinkedContentItemSuggestions = null;
try {
if (contentItem.getId() != null) {
contentEntity = pm.getObjectById(BaseContentEntity.class, contentItem.getId());
oldPublishState = contentEntity.getPublishState();
contentEntity.copyFields(contentItem);
} else {
contentEntity = BaseContentEntity.fromClientObject(contentItem);
}
if (runAutoLink) {
newLinkedContentItemSuggestions =
AutoLinkEntitiesInContent.createLinks(contentEntity, playerContentItems, concepts);
}
tx = pm.currentTransaction();
tx.begin();
pm.makePersistent(contentEntity);
tx.commit();
// If this was an event or a narrative and had a linked narrative, then the 'standalone'
// field on the narrative content item needs to be updated to 'false'.
// Note: this doesn't handle the case of unlinking a previously linked narrative content item.
// That would require checking the linked content items of every single other event
// content item to make sure it's not linked to from anywhere else, which would be an
// expensive operation.
Set<Long> linkedContentEntityIds = contentEntity.getLinkedContentEntityIds();
ContentItemType contentItemType = contentEntity.getContentItemType();
if ((contentItemType == ContentItemType.EVENT || contentItemType == ContentItemType.NARRATIVE)
&& !linkedContentEntityIds.isEmpty()) {
List<Object> oids = new ArrayList<Object>(linkedContentEntityIds.size());
for (Long id : linkedContentEntityIds) {
oids.add(pm.newObjectIdInstance(BaseContentEntity.class, id));
}
@SuppressWarnings("unchecked")
Collection<BaseContentEntity> linkedContentEntities = pm.getObjectsById(oids);
for (BaseContentEntity linkedContentEntity : linkedContentEntities) {
if (linkedContentEntity.getContentItemType() == ContentItemType.NARRATIVE) {
linkedContentEntity.setIsStandalone(false);
}
}
}
// TODO: may also want to invalidate linked content items if they changed
// and aren't from the same living story.
invalidateCache(contentItem.getLivingStoryId());
} finally {
if (tx != null && tx.isActive()) {
tx.rollback();
}
pm.close();
}
// Send email alerts if an event content item was changed from 'Draft' to 'Published'
if (contentEntity.getContentItemType() == ContentItemType.EVENT
&& contentEntity.getPublishState() == PublishState.PUBLISHED
&& oldPublishState != null && oldPublishState == PublishState.DRAFT) {
sendEmailAlerts((EventContentItem)contentItem);
}
// We pass suggested new linked content items back to the client by adding their ids to the
// client object before returning it. It's the client's responsibility to check the linked
// content item ids it passed in with those that came back, and to present appropriate
// UI for processing the suggestions. Note that we shouldn't add the suggestions directly
// to contentEntity! This will persist them to the datastore prematurely.
BaseContentItem ret = contentEntity.toClientObject();
if (newLinkedContentItemSuggestions != null) {
ret.addAllLinkedContentItemIds(newLinkedContentItemSuggestions);
}