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."); } } }