From 884a78d21719285a31eaae831fb2865e48afc7ce Mon Sep 17 00:00:00 2001 From: Sanjay Dalal Date: Fri, 30 Apr 2010 23:20:10 +0000 Subject: [PATCH] NOJIRA - added handler callbacks (prepare, handle, complete) for delete. Needed to plugin stuff affected because of CUD on entities. test: services tests --- .../document/AbstractDocumentHandlerImpl.java | 31 ++++- .../common/document/DocumentHandler.java | 26 +++- .../common/storage/StorageClient.java | 12 ++ .../storage/jpa/JpaStorageClientImpl.java | 93 +++++++++++---- .../client/java/RepositoryJavaClientImpl.java | 111 +++++++++--------- 5 files changed, 185 insertions(+), 88 deletions(-) diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java index ef756c263..9582978bd 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java @@ -80,7 +80,6 @@ public abstract class AbstractDocumentHandlerImpl // DocumentFilter docFilter = this.createDocumentFilter(ctx); // this.setDocumentFilter(docFilter); // } - @Override public abstract DocumentFilter createDocumentFilter(); @@ -121,6 +120,10 @@ public abstract class AbstractDocumentHandlerImpl prepareGetAll(); break; + case DELETE: + prepareDelete(); + break; + } } @@ -140,6 +143,10 @@ public abstract class AbstractDocumentHandlerImpl public void prepareGetAll() throws Exception { } + @Override + public void prepareDelete() throws Exception { + } + @Override final public void handle(Action action, DocumentWrapper wrapDoc) throws Exception { switch (action) { @@ -159,6 +166,10 @@ public abstract class AbstractDocumentHandlerImpl handleGetAll((DocumentWrapper) wrapDoc); break; + case DELETE: + handleDelete((DocumentWrapper) wrapDoc); + break; + } } @@ -174,6 +185,11 @@ public abstract class AbstractDocumentHandlerImpl @Override public abstract void handleGetAll(DocumentWrapper wrapDoc) throws Exception; + @Override + public void handleDelete(DocumentWrapper wrapDoc) throws Exception { + + } + @Override final public void complete(Action action, DocumentWrapper wrapDoc) throws Exception { switch (action) { @@ -192,14 +208,13 @@ public abstract class AbstractDocumentHandlerImpl case GET_ALL: completeGetAll((DocumentWrapper) wrapDoc); break; + + case DELETE: + completeDelete((DocumentWrapper) wrapDoc); + break; } } - /** - * completeCreate is called by the client to indicate completion of the create call. - * @param wrapDoc - * @throws Exception - */ @Override public void completeCreate(DocumentWrapper wrapDoc) throws Exception { } @@ -217,6 +232,10 @@ public abstract class AbstractDocumentHandlerImpl public void completeGetAll(DocumentWrapper wrapDoc) throws Exception { } + @Override + public void completeDelete(DocumentWrapper wrapDoc) throws Exception { + } + @Override public abstract T extractCommonPart(DocumentWrapper wrapDoc) throws Exception; diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java index 3e8874a9d..c6f88aeeb 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java @@ -86,19 +86,25 @@ public interface DocumentHandler { public void prepareUpdate() throws Exception; /** - * prepareGet processes query from repository before retrieving document from + * prepareGet processes query before retrieving document from * repository * @throws Exception */ public void prepareGet() throws Exception; /** - * prepareGetAll processes query from repository before retrieving document(s) from + * prepareGetAll processes query before retrieving document(s) from * repository * @throws Exception */ public void prepareGetAll() throws Exception; + /** + * prepareDelete processes delete before deleting document from repository + * @throws Exception + */ + public void prepareDelete() throws Exception; + /** * prepare is called by the client to hand over the document processing task * @param action @@ -135,6 +141,13 @@ public interface DocumentHandler { */ public void handleGetAll(DocumentWrapper wrapDoc) throws Exception; + /** + * handleDelete processes documents for the deletion of document in repository + * @param wrapDoc + * @throws Exception + */ + public void handleDelete(DocumentWrapper wrapDoc) throws Exception; + /** * complete is called by the client to provide an opportunity to the handler * to take care of stuff before closing session with the repository. example @@ -172,6 +185,13 @@ public interface DocumentHandler { */ public void completeGetAll(DocumentWrapper wrapDoc) throws Exception; + /** + * completeDelete is called by the client to indicate completion of the delete call. + * @param wrapDoc + * @throws Exception + */ + public void completeDelete(DocumentWrapper wrapDoc) throws Exception; + /** * extractCommonPart extracts common part of a CS object from given document. * this is usually called AFTER the get operation is invoked on the repository. @@ -224,7 +244,7 @@ public interface DocumentHandler { * @param properties */ public void setProperties(Map properties); - + /** * createDocumentFilter is a factory method to create a document * filter that is relevant to be used with this document handler diff --git a/services/common/src/main/java/org/collectionspace/services/common/storage/StorageClient.java b/services/common/src/main/java/org/collectionspace/services/common/storage/StorageClient.java index 8142c0bf1..05f4d386d 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/storage/StorageClient.java +++ b/services/common/src/main/java/org/collectionspace/services/common/storage/StorageClient.java @@ -50,6 +50,18 @@ public interface StorageClient { */ void delete(ServiceContext ctx, String id) throws DocumentNotFoundException, DocumentException; + + /** + * delete a entity from the persistence store + * @param ctx service context under which this method is invoked + * @param id of the entity + * @param handler to perform additional operations such as pre and post processing + * @throws DocumentNotFoundException if entity not found + * @throws DocumentException + */ + void delete(ServiceContext ctx, String id, DocumentHandler handler) throws DocumentNotFoundException, DocumentException; + + /** * get entity from the persistence store * @param ctx service context under which this method is invoked diff --git a/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java b/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java index 3e8a5bf61..e4adc202a 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java @@ -294,15 +294,7 @@ public class JpaStorageClientImpl implements StorageClient { emf = JpaStorageUtils.getEntityManagerFactory(); em = emf.createEntityManager(); em.getTransaction().begin(); - Object entityFound = em.find(entityReceived.getClass(), id); - if (entityFound == null) { - if (em != null && em.getTransaction().isActive()) { - em.getTransaction().rollback(); - } - String msg = "could not find entity with id=" + id; - logger.error(msg); - throw new DocumentNotFoundException(msg); - } + Object entityFound = getEntity(em, id, entityReceived.getClass()); DocumentWrapper wrapDoc = new DocumentWrapperImpl(entityFound); handler.handle(Action.UPDATE, wrapDoc); em.getTransaction().commit(); @@ -326,7 +318,9 @@ public class JpaStorageClientImpl implements StorageClient { } } - /* delete use delete to remove parent entityReceived along with child entities + /* + * delete removes entity and its child entities + * cost: a get before delete * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String) */ @Override @@ -334,14 +328,14 @@ public class JpaStorageClientImpl implements StorageClient { throws DocumentNotFoundException, DocumentException { + if (logger.isDebugEnabled()) { + logger.debug("deleting entity with id=" + id); + } + if (ctx == null) { throw new IllegalArgumentException( "JpaStorageClient.delete: ctx is missing"); } - - if (logger.isDebugEnabled()) { - logger.debug("deleting entity with id=" + id); - } EntityManagerFactory emf = null; EntityManager em = null; try { @@ -383,7 +377,7 @@ public class JpaStorageClientImpl implements StorageClient { * deleteWhere uses the where clause to delete an entityReceived represented by the csidReceived * it does not delete any child entities. * @param ctx - * @param csidReceived + * @param id * @throws DocumentNotFoundException * @throws DocumentException */ @@ -442,6 +436,43 @@ public class JpaStorageClientImpl implements StorageClient { } } + @Override + public void delete(ServiceContext ctx, String id, DocumentHandler handler) + throws DocumentNotFoundException, DocumentException { + if (ctx == null) { + throw new IllegalArgumentException( + "JpaStorageClient.delete: ctx is missing"); + } + if (handler == null) { + throw new IllegalArgumentException( + "JpaStorageClient.delete: handler is missing"); + } + EntityManagerFactory emf = null; + EntityManager em = null; + try { + handler.prepare(Action.DELETE); + Object entity = handler.getCommonPart(); + DocumentWrapper wrapDoc = new DocumentWrapperImpl(entity); + + handler.handle(Action.DELETE, wrapDoc); + handler.complete(Action.DELETE, wrapDoc); + } catch (DocumentException de) { + throw de; + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + if (em != null && em.getTransaction().isActive()) { + em.getTransaction().rollback(); + } + throw new DocumentException(e); + } finally { + if (emf != null) { + JpaStorageUtils.releaseEntityManagerFactory(emf); + } + } + } + /** * Gets the entityReceived name. * @@ -452,8 +483,8 @@ public class JpaStorageClientImpl implements StorageClient { protected String getEntityName(ServiceContext ctx) { Object o = ctx.getProperty(ServiceContextProperties.ENTITY_NAME); if (o == null) { - throw new IllegalArgumentException(ServiceContextProperties.ENTITY_NAME + - "property is missing in context " + throw new IllegalArgumentException(ServiceContextProperties.ENTITY_NAME + + "property is missing in context " + ctx.toString()); } @@ -462,25 +493,35 @@ public class JpaStorageClientImpl implements StorageClient { /** * getEntity returns persistent entity for given id. it assumes that - * JpaStorageClientImpl is implemented using the JpaStorageClientImpl(entityClazz) - * constructor + * service context has property ServiceContextProperties.ENTITY_CLASS set * @param ctx service context * @param em entity manager * @param csid received * @return - * @throws DocumentNotFoundException - * @throws UnsupportedOperationException if JpaStorageClientImpl is not implemented - * using the JpaStorageClientImpl(entityClazz) - * constructor + * @throws DocumentNotFoundException and rollsback the transaction if active */ - protected Object getEntity(ServiceContext ctx, EntityManager em, String id) throws DocumentNotFoundException { + protected Object getEntity(ServiceContext ctx, EntityManager em, String id) + throws DocumentNotFoundException { Class entityClazz = (Class) ctx.getProperty(ServiceContextProperties.ENTITY_CLASS); if (entityClazz == null) { - String msg = ServiceContextProperties.ENTITY_CLASS + - " property is missing in the context"; + String msg = ServiceContextProperties.ENTITY_CLASS + + " property is missing in the context"; logger.error(msg); throw new IllegalArgumentException(msg); } + return getEntity(em, id, entityClazz); + } + + /** + * getEntity retrieves the persistent entity of given class for given id + * @param em + * @param id entity id + * @param entityClazz + * @return + * @throws DocumentNotFoundException and rollsback the transaction if active + */ + protected Object getEntity(EntityManager em, String id, Class entityClazz) + throws DocumentNotFoundException { Object entityFound = JpaStorageUtils.getEntity(em, id, entityClazz); if (entityFound == null) { if (em != null && em.getTransaction().isActive()) { diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java index d9d033033..422569706 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java @@ -123,7 +123,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient { } } - + /** * get document from the Nuxeo repository * @param ctx service context under which this method is invoked @@ -196,15 +196,15 @@ public class RepositoryJavaClientImpl implements RepositoryClient { DocumentFilter docFilter = handler.getDocumentFilter(); if (docFilter == null) { throw new IllegalArgumentException( - "RepositoryJavaClient.get: handler has no Filter specified"); + "RepositoryJavaClient.get: handler has no Filter specified"); } - if(docFilter.getPageSize()!= 1) { + if (docFilter.getPageSize() != 1) { logger.warn("RepositoryJavaClient.get: forcing docFilter pagesize to 1."); } String docType = ctx.getDocumentType(); if (docType == null) { throw new DocumentNotFoundException( - "Unable to find DocumentType for service " + ctx.getServiceName()); + "Unable to find DocumentType for service " + ctx.getServiceName()); } String domain = ctx.getRepositoryDomainName(); if (domain == null) { @@ -216,20 +216,20 @@ public class RepositoryJavaClientImpl implements RepositoryClient { try { handler.prepare(Action.GET); repoSession = getRepositorySession(); - + DocumentModelList docList = null; // force limit to 1, and ignore totalSize - String query = buildNXQLQuery(docType, docFilter.getWhereClause(), domain ); - docList = repoSession.query( query, null, 1, 0, false); - if(docList.size()!=1) { + String query = buildNXQLQuery(docType, docFilter.getWhereClause(), domain); + docList = repoSession.query(query, null, 1, 0, false); + if (docList.size() != 1) { throw new DocumentNotFoundException("No document found matching filter params."); } DocumentModel doc = docList.get(0); - + if (logger.isDebugEnabled()) { logger.debug("Executed NXQL query: " + query); } - + //set reposession to handle the document ((DocumentModelHandler) handler).setRepositorySession(repoSession); DocumentWrapper wrapDoc = new DocumentWrapperImpl(doc); @@ -260,7 +260,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient { */ @Override public DocumentWrapper getDoc( - ServiceContext ctx, String id) + ServiceContext ctx, String id) throws DocumentNotFoundException, DocumentException { RepositoryInstance repoSession = null; DocumentWrapper wrapDoc = null; @@ -302,16 +302,16 @@ public class RepositoryJavaClientImpl implements RepositoryClient { */ @Override public DocumentWrapper findDoc( - ServiceContext ctx, String where) + ServiceContext ctx, String where) throws DocumentNotFoundException, DocumentException { RepositoryInstance repoSession = null; DocumentWrapper wrapDoc = null; try { - String docType = ctx.getDocumentType(); + String docType = ctx.getDocumentType(); if (docType == null) { throw new DocumentNotFoundException( - "Unable to find DocumentType for service " + ctx.getServiceName()); + "Unable to find DocumentType for service " + ctx.getServiceName()); } String domain = ctx.getRepositoryDomainName(); if (domain == null) { @@ -321,11 +321,11 @@ public class RepositoryJavaClientImpl implements RepositoryClient { repoSession = getRepositorySession(); DocumentModelList docList = null; // force limit to 1, and ignore totalSize - String query = buildNXQLQuery(docType, where, domain ); - docList = repoSession.query( query, null, 1, 0, false); - if(docList.size()!=1) { + String query = buildNXQLQuery(docType, where, domain); + docList = repoSession.query(query, null, 1, 0, false); + if (docList.size() != 1) { if (logger.isDebugEnabled()) { - logger.debug("findDoc: Query found: "+docList.size()+" items."); + logger.debug("findDoc: Query found: " + docList.size() + " items."); logger.debug(" Query: " + query); } throw new DocumentNotFoundException("No document found matching filter params."); @@ -348,7 +348,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient { } return wrapDoc; } - + /** * find doc and return CSID from the Nuxeo repository * @param ctx service context under which this method is invoked @@ -356,26 +356,26 @@ public class RepositoryJavaClientImpl implements RepositoryClient { * @throws DocumentException */ public String findDocCSID( - ServiceContext ctx, String where) + ServiceContext ctx, String where) throws DocumentNotFoundException, DocumentException { - String csid = null; - try { - DocumentWrapper wrapDoc = findDoc(ctx, where); - DocumentModel docModel = wrapDoc.getWrappedObject(); + String csid = null; + try { + DocumentWrapper wrapDoc = findDoc(ctx, where); + DocumentModel docModel = wrapDoc.getWrappedObject(); csid = NuxeoUtils.extractId(docModel.getPathAsString()); - } catch (DocumentNotFoundException dnfe) { + } catch (DocumentNotFoundException dnfe) { throw dnfe; } catch (IllegalArgumentException iae) { throw iae; } catch (DocumentException de) { throw de; - } catch (Exception e) { + } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception ", e); } throw new DocumentException(e); } - return csid; + return csid; } /** @@ -387,16 +387,16 @@ public class RepositoryJavaClientImpl implements RepositoryClient { */ @Override public DocumentWrapper findDocs( - List docTypes, String where, String domain, - int pageSize, int pageNum, boolean computeTotal ) + List docTypes, String where, String domain, + int pageSize, int pageNum, boolean computeTotal) throws DocumentNotFoundException, DocumentException { RepositoryInstance repoSession = null; DocumentWrapper wrapDoc = null; try { - if (docTypes == null || docTypes.size()<1) { + if (docTypes == null || docTypes.size() < 1) { throw new DocumentNotFoundException( - "findDocs must specify at least one DocumentType."); + "findDocs must specify at least one DocumentType."); } if (domain == null) { throw new DocumentNotFoundException("findDocs must specify Domain."); @@ -404,8 +404,8 @@ public class RepositoryJavaClientImpl implements RepositoryClient { repoSession = getRepositorySession(); DocumentModelList docList = null; // force limit to 1, and ignore totalSize - String query = buildNXQLQuery(docTypes, where, domain ); - docList = repoSession.query( query, null, pageSize, pageNum, computeTotal); + String query = buildNXQLQuery(docTypes, where, domain); + docList = repoSession.query(query, null, pageSize, pageNum, computeTotal); wrapDoc = new DocumentWrapperImpl(docList); } catch (IllegalArgumentException iae) { throw iae; @@ -422,10 +422,9 @@ public class RepositoryJavaClientImpl implements RepositoryClient { return wrapDoc; } - @Override public void get(ServiceContext ctx, List csidList, DocumentHandler handler) - throws DocumentNotFoundException, DocumentException { + throws DocumentNotFoundException, DocumentException { if (handler == null) { throw new IllegalArgumentException( "RepositoryJavaClient.getAll: handler is missing"); @@ -462,7 +461,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient { } } } - + /** * getAll get all documents for an entity entity service from the Nuxeo * repository @@ -547,7 +546,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient { handler.prepare(Action.GET_ALL); repoSession = getRepositorySession(); DocumentModelList docList = null; - String query = buildNXQLQuery(docType, docFilter.getWhereClause(), domain ); + String query = buildNXQLQuery(docType, docFilter.getWhereClause(), domain); // If we have limit and/or offset, then pass true to get totalSize // in returned DocumentModelList. @@ -557,11 +556,11 @@ public class RepositoryJavaClientImpl implements RepositoryClient { } else { docList = repoSession.query(query); } - + if (logger.isDebugEnabled()) { logger.debug("Executed NXQL query: " + query.toString()); } - + //set repoSession to handle the document ((DocumentModelHandler) handler).setRepositorySession(repoSession); DocumentWrapper wrapDoc = new DocumentWrapperImpl(docList); @@ -676,6 +675,12 @@ public class RepositoryJavaClientImpl implements RepositoryClient { } } + @Override + public void delete(ServiceContext ctx, String id, DocumentHandler handler) + throws DocumentNotFoundException, DocumentException { + throw new UnsupportedOperationException(); + } + @Override public String createWorkspace(String tenantDomain, String workspaceName) throws Exception { RepositoryInstance repoSession = null; @@ -737,38 +742,38 @@ public class RepositoryJavaClientImpl implements RepositoryClient { } return workspaceId; } - - private final void appendNXQLWhere(StringBuilder query, String where, String domain ) { + + private final void appendNXQLWhere(StringBuilder query, String where, String domain) { // TODO This is a slow method for tenant-filter // We should make this a property that is indexed. query.append(" WHERE ecm:path STARTSWITH '/" + domain + "'"); if ((null != where) && (where.length() > 0)) { - // Due to an apparent bug/issue in how Nuxeo translates the NXQL query string - // into SQL, we need to parenthesize our 'where' clause - query.append(" AND " + "(" + where +")"); + // Due to an apparent bug/issue in how Nuxeo translates the NXQL query string + // into SQL, we need to parenthesize our 'where' clause + query.append(" AND " + "(" + where + ")"); } query.append(" AND ecm:isProxy = 0"); } - private final String buildNXQLQuery(String docType, String where, String domain ) { + private final String buildNXQLQuery(String docType, String where, String domain) { StringBuilder query = new StringBuilder("SELECT * FROM "); query.append(docType); - appendNXQLWhere(query, where, domain ); + appendNXQLWhere(query, where, domain); return query.toString(); } - private final String buildNXQLQuery(List docTypes, String where, String domain ) { + private final String buildNXQLQuery(List docTypes, String where, String domain) { StringBuilder query = new StringBuilder("SELECT * FROM "); boolean fFirst = true; - for(String docType:docTypes) { - if(fFirst) { + for (String docType : docTypes) { + if (fFirst) { fFirst = false; - } else { - query.append(","); - } + } else { + query.append(","); + } query.append(docType); } - appendNXQLWhere(query, where, domain ); + appendNXQLWhere(query, where, domain); return query.toString(); } -- 2.47.3