package org.aplikator.server.data;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.aplikator.client.shared.data.Operation;
import org.aplikator.client.shared.data.PrimaryKey;
import org.aplikator.client.shared.rpc.AplikatorException;
import org.aplikator.server.DescriptorRegistry;
import org.aplikator.server.descriptor.BinaryProperty;
import org.aplikator.server.descriptor.Collection;
import org.aplikator.server.descriptor.Property;
import org.aplikator.server.descriptor.SortItem;
import org.aplikator.server.descriptor.View;
import org.aplikator.server.persistence.Persister;
import org.aplikator.server.persistence.PersisterFactory;
import org.aplikator.server.persistence.search.ReindexDescriptor;
import org.aplikator.server.persistence.search.SearchFactory;
import org.aplikator.server.persistence.tempstore.Tempstore;
import org.aplikator.server.persistence.tempstore.TempstoreFactory;
import org.aplikator.server.query.QueryExpression;
/**
* The server side implementation of the RPC service.
*/
public class AplikatorServiceBackend {
private static final Logger LOG = Logger.getLogger(AplikatorServiceBackend.class.getName());
Persister persister = PersisterFactory.getPersister();
public AplikatorServiceBackend() {
}
private void processAfterCommit(RecordContainer rc, Context ctx) {
for (ContainerNode containerNode : rc.getRecords()) {
PersisterTriggers trigger = containerNode.getView().getPersisterTriggers();
trigger.afterCommit(containerNode, ctx);
}
}
public RecordContainer processRecords(RecordContainer rc, Context ctx) {
LOG.info("processing container");
checkSuspendedState();
ReindexDescriptor reindexDescriptor = new ReindexDescriptor();
try {
for (int progressIter = 0; progressIter < rc.getRecords().size(); progressIter++) {
ContainerNode node = rc.getRecords().get(progressIter);
PersisterTriggers trigger = node.getView().getPersisterTriggers();
loadBinaryData(node.getEdited());
switch (node.getOperation()) {
case CREATE:
trigger.onCreate(node, ctx);
node.setEdited(persister.updateRecord(node.getEdited(), ctx));
if (node.getView().getEntity().isIndexed()) {
reindexDescriptor.addDescriptor(node.getEdited().getPrimaryKey(), Operation.CREATE);
}
trigger.onLoad(node.getEdited(), node.getView(), ctx);
break;
case UPDATE:
trigger.onUpdate(node, ctx);
persister.updateRecord(node.getEdited(), ctx);
reindexDescriptor.addDescriptor(node.getEdited().getPrimaryKey(), Operation.UPDATE);
trigger.onLoad(node.getEdited(), node.getView(), ctx);
break;
case DELETE:
trigger.onDelete(node, ctx);
persister.deleteRecord(node.getOriginal(), ctx);
reindexDescriptor.addDescriptor(node.getOriginal().getPrimaryKey(), Operation.DELETE);
break;
}
}
if (SearchFactory.isSearchEnabled()) {
reindexDescriptor.processReindex(ctx);
}
persister.commitTransaction(ctx.getTransaction());
processAfterCommit(rc, ctx);
} catch (Throwable th) {
if (ctx.getTransaction() != null)
persister.rollbackTransaction(ctx.getTransaction());
LOG.log(Level.SEVERE, "Error in processing records:", th);
Throwable rootEx = th;
while (rootEx.getCause() != null) {
rootEx = rootEx.getCause();
}
throw new AplikatorException(rootEx.getMessage(), rootEx);
}
for (ContainerNode cn : rc.getRecords()) {
if (cn.getOperation().equals(Operation.CREATE) || cn.getOperation().equals(Operation.UPDATE)) {
PrimaryKey pk = cn.getEdited().getPrimaryKey();
View view = cn.getView();
Record updated = persister.getRecord(view, pk, ctx);
if (cn.getOperation().equals(Operation.CREATE)) {
updated.getPrimaryKey().setTempId(pk.getTempId());
}
cn.setOriginal(updated);
} else {
cn.setOriginal(null);
}
cn.setEdited(null);
}
return rc;
}
private void loadBinaryData(Record record) {
if (record == null)
return;
Tempstore ts = TempstoreFactory.getTempstore();
for (String id : record.getRecordDTO().getProperties()) {
Property<? extends Serializable> p = (Property<? extends Serializable>) DescriptorRegistry.get().getDescriptionItem(id);
if (p == null || p.getRefferedThrough() != null || !p.getType().equals(BinaryData.class)) {
continue;
}
BinaryData binaryData = null;
if (record.getValue(p) instanceof BinaryData) {
binaryData = (BinaryData) record.getValue(p);
} else {
String fileId = (String) record.getValue(p);
if (fileId == null || "".equals(fileId)) {
continue;
}
String filename = ts.getFilename(fileId);
binaryData = new BinaryData((BinaryProperty) p, filename, ts.load(fileId), ts.getFileLength(fileId), fileId);
}
String[] s = p.getFormatPattern().split(",");
int thumbnailSize = Integer.parseInt(s[0]);
int previewSize = Integer.parseInt(s[1]);
binaryData.preprocess(thumbnailSize, previewSize);
@SuppressWarnings("unchecked")
BinaryProperty prop = (BinaryProperty) p;
record.setValue(prop, binaryData);
}
}
public Record getRecord(PrimaryKey primaryKey, View view, Context ctx) {
try {
return persister.getRecord(view, primaryKey, ctx);
} catch (Throwable t) {
LOG.log(Level.SEVERE, "Error in getRecord: " + t.getMessage(), t);
throw new RuntimeException("Error in getRecord: " + t.getMessage(), t);
}
}
public int getRecordCount(View view, QueryExpression queryExpression, SortItem[] sortItems, String searchString, Collection ownerProperty, PrimaryKey ownerPrimaryKey, Context ctx) {
try {
return persister.getRecordCount(view, queryExpression, sortItems, searchString, ownerProperty, ownerPrimaryKey, ctx);
} catch (Throwable t) {
LOG.log(Level.SEVERE, "Error in getRecordCount: " + t.getMessage(), t);
throw new RuntimeException("Error in getRecordCount: " + t.getMessage(), t);
}
}
public Record getCompleteRecord(String primaryKey, int traverseLevel, boolean includeCollections, Context ctx) {
try {
Record completeRecord = persister.getCompleteRecord(new PrimaryKey(primaryKey), traverseLevel, includeCollections, ctx);
return completeRecord;
} catch (Throwable t) {
LOG.log(Level.SEVERE, "Error in getCompleteRecord: " + t.getMessage(), t);
throw new RuntimeException("Error in getCompleteRecord: " + t.getMessage(), t);
}
}
public RecordContainer prepareRecord(PrimaryKey primaryKey, View view, Collection ownerProperty, PrimaryKey ownerPrimaryKey, Context ctx) {
checkSuspendedState();
try {
RecordContainer retval = ctx.getRecordContainer();
Record original = null;
Record edited = null;
if (primaryKey != null) {
original = persister.getRecord(view, primaryKey, ctx);
edited = original.clone();
edited.setPrimaryKey(new PrimaryKey(view.getEntity().getId(), UUID.randomUUID().toString()));
} else {
edited = RecordUtils.newRecord(view.getEntity());
}
if (ownerProperty != null) {
edited.setOwnerPrimaryKey(ownerPrimaryKey);
edited.setOwnerProperty(ownerProperty);
}
retval.addRecord(view, original, edited, Operation.PREPARE);
ContainerNode node = retval.getRecords().get(0);
PersisterTriggers trigger = view.getPersisterTriggers();
trigger.onPrepare(node, primaryKey != null, ctx);
return retval;
} catch (Throwable t) {
LOG.log(Level.SEVERE, "Error in prepareRecord: " + t.getMessage(), t);
throw new RuntimeException("Error in prepareRecord: " + t.getMessage(), t);
}
}
public List<Record> getRecords(View view, QueryExpression queryExpression, SortItem[] sortItems, String searchString, Collection ownerProperty, PrimaryKey ownerPrimaryKey, int pageOffset, int pageSize, Context ctx) {
return persister.getRecords(view, queryExpression, sortItems, searchString, ownerProperty, ownerPrimaryKey, pageOffset, pageSize, ctx);
}
void checkSuspendedState() {
if (persister.isSuspended()) {
throw new RuntimeException("Application is in the suspended state.");
}
}
}