2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
18 package org.collectionspace.services.nuxeo.client.java;
20 import java.util.Hashtable;
21 import java.util.UUID;
22 import java.util.List;
24 import org.collectionspace.services.common.context.ServiceContext;
25 import org.collectionspace.services.common.query.IQueryManager;
26 import org.collectionspace.services.common.query.QueryContext;
27 import org.collectionspace.services.common.repository.RepositoryClient;
28 import org.collectionspace.services.common.profile.Profiler;
29 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
31 import org.collectionspace.services.common.document.BadRequestException;
32 import org.collectionspace.services.common.document.DocumentException;
33 import org.collectionspace.services.common.document.DocumentFilter;
34 import org.collectionspace.services.common.document.DocumentHandler;
35 import org.collectionspace.services.common.document.DocumentNotFoundException;
36 import org.collectionspace.services.common.document.DocumentHandler.Action;
37 import org.collectionspace.services.common.document.DocumentWrapper;
38 import org.collectionspace.services.common.document.DocumentWrapperImpl;
40 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
41 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
43 import org.nuxeo.common.utils.IdUtils;
44 import org.nuxeo.ecm.core.api.ClientException;
45 import org.nuxeo.ecm.core.api.DocumentModel;
46 import org.nuxeo.ecm.core.api.DocumentModelList;
47 import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
48 import org.nuxeo.ecm.core.api.DocumentRef;
49 import org.nuxeo.ecm.core.api.IdRef;
50 import org.nuxeo.ecm.core.api.PathRef;
51 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
52 import org.nuxeo.ecm.core.client.NuxeoClient;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
58 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
59 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
62 * $LastChangedRevision: $ $LastChangedDate: $
64 public class RepositoryJavaClientImpl implements RepositoryClient {
67 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class);
68 // private final Logger profilerLogger = LoggerFactory.getLogger("remperf");
69 // private String foo = Profiler.createLogger();
71 * Instantiates a new repository java client impl.
73 public RepositoryJavaClientImpl() {
79 * Sets the collection space core values.
82 * @param documentModel the document model
83 * @throws ClientException the client exception
85 private void setCollectionSpaceCoreValues(ServiceContext<MultipartInput, MultipartOutput> ctx,
86 DocumentModel documentModel,
87 Action action) throws ClientException {
89 // Add the tenant ID value to the new entity
91 documentModel.setProperty(DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA,
92 DocumentModelHandler.COLLECTIONSPACE_CORE_TENANTID,
96 //add creation date value
106 * create document in the Nuxeo repository
108 * @param ctx service context under which this method is invoked
110 * of the document created
112 * should be used by the caller to provide and transform the
114 * @return id in repository of the newly created document
115 * @throws DocumentException
118 public String create(ServiceContext ctx,
119 DocumentHandler handler) throws BadRequestException,
122 if (ctx.getDocumentType() == null) {
123 throw new IllegalArgumentException(
124 "RepositoryJavaClient.create: docType is missing");
126 if (handler == null) {
127 throw new IllegalArgumentException(
128 "RepositoryJavaClient.create: handler is missing");
130 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
131 if (nuxeoWspaceId == null) {
132 throw new DocumentNotFoundException(
133 "Unable to find workspace for service " + ctx.getServiceName()
134 + " check if the workspace exists in the Nuxeo repository");
136 RepositoryInstance repoSession = null;
138 handler.prepare(Action.CREATE);
139 repoSession = getRepositorySession();
140 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
141 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
142 String wspacePath = wspaceDoc.getPathAsString();
143 //give our own ID so PathRef could be constructed later on
144 String id = IdUtils.generateId(UUID.randomUUID().toString());
145 // create document model
146 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id,
147 ctx.getDocumentType());
148 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
149 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
150 handler.handle(Action.CREATE, wrapDoc);
151 // create document with documentmodel
152 setCollectionSpaceCoreValues(ctx, doc, Action.CREATE);
153 doc = repoSession.createDocument(doc);
155 // TODO for sub-docs need to call into the handler to let it deal with subitems. Pass in the id,
156 // and assume the handler has the state it needs (doc fragments).
157 handler.complete(Action.CREATE, wrapDoc);
159 } catch (BadRequestException bre) {
161 } catch (Exception e) {
162 if (logger.isDebugEnabled()) {
163 logger.debug("Caught exception ", e);
165 throw new DocumentException(e);
167 if (repoSession != null) {
168 releaseRepositorySession(repoSession);
175 * get document from the Nuxeo repository
176 * @param ctx service context under which this method is invoked
178 * of the document to retrieve
180 * should be used by the caller to provide and transform the
182 * @throws DocumentException
185 public void get(ServiceContext ctx, String id, DocumentHandler handler)
186 throws DocumentNotFoundException, DocumentException {
188 if (handler == null) {
189 throw new IllegalArgumentException(
190 "RepositoryJavaClient.get: handler is missing");
192 RepositoryInstance repoSession = null;
195 handler.prepare(Action.GET);
196 repoSession = getRepositorySession();
197 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
198 DocumentModel doc = null;
200 doc = repoSession.getDocument(docRef);
201 } catch (ClientException ce) {
202 String msg = "could not find document with id=" + id;
203 logger.error(msg, ce);
204 throw new DocumentNotFoundException(msg, ce);
206 //set reposession to handle the document
207 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
208 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
209 handler.handle(Action.GET, wrapDoc);
210 handler.complete(Action.GET, wrapDoc);
211 } catch (IllegalArgumentException iae) {
213 } catch (DocumentException de) {
215 } catch (Exception e) {
216 if (logger.isDebugEnabled()) {
217 logger.debug("Caught exception ", e);
219 throw new DocumentException(e);
221 if (repoSession != null) {
222 releaseRepositorySession(repoSession);
228 * get document from the Nuxeo repository, using the docFilter params.
229 * @param ctx service context under which this method is invoked
231 * should be used by the caller to provide and transform the
232 * document. Handler must have a docFilter set to return a single item.
233 * @throws DocumentException
236 public void get(ServiceContext ctx, DocumentHandler handler)
237 throws DocumentNotFoundException, DocumentException {
238 QueryContext queryContext = new QueryContext(ctx, handler);
239 RepositoryInstance repoSession = null;
242 handler.prepare(Action.GET);
243 repoSession = getRepositorySession();
245 DocumentModelList docList = null;
246 // force limit to 1, and ignore totalSize
247 String query = buildNXQLQuery(queryContext);
248 docList = repoSession.query(query, null, 1, 0, false);
249 if (docList.size() != 1) {
250 throw new DocumentNotFoundException("No document found matching filter params.");
252 DocumentModel doc = docList.get(0);
254 if (logger.isDebugEnabled()) {
255 logger.debug("Executed NXQL query: " + query);
258 //set reposession to handle the document
259 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
260 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
261 handler.handle(Action.GET, wrapDoc);
262 handler.complete(Action.GET, wrapDoc);
263 } catch (IllegalArgumentException iae) {
265 } catch (DocumentException de) {
267 } catch (Exception e) {
268 if (logger.isDebugEnabled()) {
269 logger.debug("Caught exception ", e);
271 throw new DocumentException(e);
273 if (repoSession != null) {
274 releaseRepositorySession(repoSession);
280 * get wrapped documentModel from the Nuxeo repository
281 * @param ctx service context under which this method is invoked
283 * of the document to retrieve
284 * @throws DocumentException
287 public DocumentWrapper<DocumentModel> getDoc(
288 ServiceContext ctx, String id)
289 throws DocumentNotFoundException, DocumentException {
290 RepositoryInstance repoSession = null;
291 DocumentWrapper<DocumentModel> wrapDoc = null;
294 repoSession = getRepositorySession();
295 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
296 DocumentModel doc = null;
298 doc = repoSession.getDocument(docRef);
299 } catch (ClientException ce) {
300 String msg = "could not find document with id=" + id;
301 logger.error(msg, ce);
302 throw new DocumentNotFoundException(msg, ce);
304 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
305 } catch (IllegalArgumentException iae) {
307 } catch (DocumentException de) {
309 } catch (Exception e) {
310 if (logger.isDebugEnabled()) {
311 logger.debug("Caught exception ", e);
313 throw new DocumentException(e);
315 if (repoSession != null) {
316 releaseRepositorySession(repoSession);
323 * find wrapped documentModel from the Nuxeo repository
324 * @param ctx service context under which this method is invoked
325 * @param where NXQL where clause to get the document
326 * @throws DocumentException
329 public DocumentWrapper<DocumentModel> findDoc(
330 ServiceContext ctx, String whereClause)
331 throws DocumentNotFoundException, DocumentException {
332 RepositoryInstance repoSession = null;
333 DocumentWrapper<DocumentModel> wrapDoc = null;
336 QueryContext queryContext = new QueryContext(ctx, whereClause);
337 repoSession = getRepositorySession();
338 DocumentModelList docList = null;
339 // force limit to 1, and ignore totalSize
340 String query = buildNXQLQuery(queryContext);
341 docList = repoSession.query(query,
346 if (docList.size() != 1) {
347 if (logger.isDebugEnabled()) {
348 logger.debug("findDoc: Query found: " + docList.size() + " items.");
349 logger.debug(" Query: " + query);
351 throw new DocumentNotFoundException("No document found matching filter params.");
353 DocumentModel doc = docList.get(0);
354 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
355 } catch (IllegalArgumentException iae) {
357 } catch (DocumentException de) {
359 } catch (Exception e) {
360 if (logger.isDebugEnabled()) {
361 logger.debug("Caught exception ", e);
363 throw new DocumentException(e);
365 if (repoSession != null) {
366 releaseRepositorySession(repoSession);
373 * find doc and return CSID from the Nuxeo repository
374 * @param ctx service context under which this method is invoked
375 * @param where NXQL where clause to get the document
376 * @throws DocumentException
379 public String findDocCSID(
380 ServiceContext ctx, String whereClause)
381 throws DocumentNotFoundException, DocumentException {
384 DocumentWrapper<DocumentModel> wrapDoc = findDoc(ctx, whereClause);
385 DocumentModel docModel = wrapDoc.getWrappedObject();
386 csid = NuxeoUtils.extractId(docModel.getPathAsString());
387 } catch (DocumentNotFoundException dnfe) {
389 } catch (IllegalArgumentException iae) {
391 } catch (DocumentException de) {
393 } catch (Exception e) {
394 if (logger.isDebugEnabled()) {
395 logger.debug("Caught exception ", e);
397 throw new DocumentException(e);
403 * Find a list of documentModels from the Nuxeo repository
404 * @param docTypes a list of DocType names to match
405 * @param where the clause to qualify on
406 * @param domain the domain for the associated services
410 public DocumentWrapper<DocumentModelList> findDocs(
412 List<String> docTypes,
414 int pageSize, int pageNum, boolean computeTotal)
415 throws DocumentNotFoundException, DocumentException {
416 RepositoryInstance repoSession = null;
417 DocumentWrapper<DocumentModelList> wrapDoc = null;
420 if (docTypes == null || docTypes.size() < 1) {
421 throw new DocumentNotFoundException(
422 "findDocs must specify at least one DocumentType.");
424 repoSession = getRepositorySession();
425 DocumentModelList docList = null;
426 // force limit to 1, and ignore totalSize
427 QueryContext queryContext = new QueryContext(ctx, whereClause);
428 String query = buildNXQLQuery(docTypes, queryContext);
429 docList = repoSession.query(query, null, pageSize, pageNum, computeTotal);
430 wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
431 } catch (IllegalArgumentException iae) {
433 } catch (Exception e) {
434 if (logger.isDebugEnabled()) {
435 logger.debug("Caught exception ", e);
437 throw new DocumentException(e);
439 if (repoSession != null) {
440 releaseRepositorySession(repoSession);
447 * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.util.List, org.collectionspace.services.common.document.DocumentHandler)
450 public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
451 throws DocumentNotFoundException, DocumentException {
452 if (handler == null) {
453 throw new IllegalArgumentException(
454 "RepositoryJavaClient.getAll: handler is missing");
457 RepositoryInstance repoSession = null;
460 handler.prepare(Action.GET_ALL);
461 repoSession = getRepositorySession();
462 DocumentModelList docModelList = new DocumentModelListImpl();
463 //FIXME: Should be using NuxeoUtils.createPathRef for security reasons
464 for (String csid : csidList) {
465 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
466 DocumentModel docModel = repoSession.getDocument(docRef);
467 docModelList.add(docModel);
470 //set reposession to handle the document
471 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
472 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docModelList);
473 handler.handle(Action.GET_ALL, wrapDoc);
474 handler.complete(Action.GET_ALL, wrapDoc);
475 } catch (DocumentException de) {
477 } catch (Exception e) {
478 if (logger.isDebugEnabled()) {
479 logger.debug("Caught exception ", e);
481 throw new DocumentException(e);
483 if (repoSession != null) {
484 releaseRepositorySession(repoSession);
490 * getAll get all documents for an entity entity service from the Nuxeo
493 * @param ctx service context under which this method is invoked
495 * should be used by the caller to provide and transform the
497 * @throws DocumentException
500 public void getAll(ServiceContext ctx, DocumentHandler handler)
501 throws DocumentNotFoundException, DocumentException {
502 if (handler == null) {
503 throw new IllegalArgumentException(
504 "RepositoryJavaClient.getAll: handler is missing");
506 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
507 if (nuxeoWspaceId == null) {
508 throw new DocumentNotFoundException(
509 "Unable to find workspace for service "
510 + ctx.getServiceName()
511 + " check if the workspace exists in the Nuxeo repository");
513 RepositoryInstance repoSession = null;
516 handler.prepare(Action.GET_ALL);
517 repoSession = getRepositorySession();
518 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
519 DocumentModelList docList = repoSession.getChildren(wsDocRef);
520 //set reposession to handle the document
521 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
522 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
523 handler.handle(Action.GET_ALL, wrapDoc);
524 handler.complete(Action.GET_ALL, wrapDoc);
525 } catch (DocumentException de) {
527 } catch (Exception e) {
528 if (logger.isDebugEnabled()) {
529 logger.debug("Caught exception ", e);
531 throw new DocumentException(e);
533 if (repoSession != null) {
534 releaseRepositorySession(repoSession);
540 * getFiltered get all documents for an entity service from the Document repository,
541 * given filter parameters specified by the handler.
542 * @param ctx service context under which this method is invoked
543 * @param handler should be used by the caller to provide and transform the document
544 * @throws DocumentNotFoundException if workspace not found
545 * @throws DocumentException
548 public void getFiltered(ServiceContext ctx, DocumentHandler handler)
549 throws DocumentNotFoundException, DocumentException {
550 QueryContext queryContext = new QueryContext(ctx, handler);
552 RepositoryInstance repoSession = null;
554 handler.prepare(Action.GET_ALL);
555 repoSession = getRepositorySession();
556 DocumentModelList docList = null;
557 String query = buildNXQLQuery(queryContext);
559 if (logger.isDebugEnabled()) {
560 logger.debug("Executing NXQL query: " + query.toString());
563 // If we have limit and/or offset, then pass true to get totalSize
564 // in returned DocumentModelList.
565 Profiler profiler = new Profiler(this, 2);
566 profiler.log("Executing NXQL query: " + query.toString());
568 if ((queryContext.getDocFilter().getOffset() > 0) || (queryContext.getDocFilter().getPageSize() > 0)) {
569 docList = repoSession.query(query, null,
570 queryContext.getDocFilter().getPageSize(), queryContext.getDocFilter().getOffset(), true);
572 docList = repoSession.query(query);
576 //set repoSession to handle the document
577 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
578 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
579 handler.handle(Action.GET_ALL, wrapDoc);
580 handler.complete(Action.GET_ALL, wrapDoc);
581 } catch (DocumentException de) {
583 } catch (Exception e) {
584 if (logger.isDebugEnabled()) {
585 logger.debug("Caught exception ", e);
587 throw new DocumentException(e);
589 if (repoSession != null) {
590 releaseRepositorySession(repoSession);
596 * update given document in the Nuxeo repository
598 * @param ctx service context under which this method is invoked
602 * should be used by the caller to provide and transform the
604 * @throws DocumentException
607 public void update(ServiceContext ctx, String id, DocumentHandler handler)
608 throws BadRequestException, DocumentNotFoundException,
610 if (handler == null) {
611 throw new IllegalArgumentException(
612 "RepositoryJavaClient.update: handler is missing");
614 RepositoryInstance repoSession = null;
616 handler.prepare(Action.UPDATE);
617 repoSession = getRepositorySession();
618 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
619 DocumentModel doc = null;
621 doc = repoSession.getDocument(docRef);
622 } catch (ClientException ce) {
623 String msg = "Could not find document to update with id=" + id;
624 logger.error(msg, ce);
625 throw new DocumentNotFoundException(msg, ce);
627 //set reposession to handle the document
628 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
629 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
630 handler.handle(Action.UPDATE, wrapDoc);
631 setCollectionSpaceCoreValues(ctx, doc, Action.CREATE);
632 repoSession.saveDocument(doc);
634 handler.complete(Action.UPDATE, wrapDoc);
635 } catch (BadRequestException bre) {
637 } catch (DocumentException de) {
639 } catch (Exception e) {
640 if (logger.isDebugEnabled()) {
641 logger.debug("Caught exception ", e);
643 throw new DocumentException(e);
645 if (repoSession != null) {
646 releaseRepositorySession(repoSession);
652 * delete a document from the Nuxeo repository
653 * @param ctx service context under which this method is invoked
656 * @throws DocumentException
659 public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
662 if (logger.isDebugEnabled()) {
663 logger.debug("deleting document with id=" + id);
665 RepositoryInstance repoSession = null;
667 repoSession = getRepositorySession();
668 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
670 repoSession.removeDocument(docRef);
671 } catch (ClientException ce) {
672 String msg = "could not find document to delete with id=" + id;
673 logger.error(msg, ce);
674 throw new DocumentNotFoundException(msg, ce);
677 } catch (DocumentException de) {
679 } catch (Exception e) {
680 if (logger.isDebugEnabled()) {
681 logger.debug("Caught exception ", e);
683 throw new DocumentException(e);
685 if (repoSession != null) {
686 releaseRepositorySession(repoSession);
692 * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
695 public void delete(ServiceContext ctx, String id, DocumentHandler handler)
696 throws DocumentNotFoundException, DocumentException {
697 throw new UnsupportedOperationException();
701 public Hashtable<String, String> retrieveWorkspaceIds(String domainName) throws Exception {
702 return NuxeoConnector.getInstance().retrieveWorkspaceIds(domainName);
706 public String createDomain(String domainName) throws Exception {
707 RepositoryInstance repoSession = null;
708 String domainId = null;
710 repoSession = getRepositorySession();
711 DocumentRef parentDocRef = new PathRef("/");
712 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
713 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
714 domainName, "Domain");
715 doc.setPropertyValue("dc:title", domainName);
716 doc.setPropertyValue("dc:description", "A CollectionSpace domain "
718 doc = repoSession.createDocument(doc);
719 domainId = doc.getId();
721 if (logger.isDebugEnabled()) {
722 logger.debug("created tenant domain name=" + domainName
723 + " id=" + domainId);
725 } catch (Exception e) {
726 if (logger.isDebugEnabled()) {
727 logger.debug("createTenantSpace caught exception ", e);
731 if (repoSession != null) {
732 releaseRepositorySession(repoSession);
739 public String getDomainId(String domainName) throws Exception {
740 String domainId = null;
741 RepositoryInstance repoSession = null;
743 repoSession = getRepositorySession();
744 DocumentRef docRef = new PathRef(
746 DocumentModel domain = repoSession.getDocument(docRef);
747 domainId = domain.getId();
748 } catch (Exception e) {
749 if (logger.isDebugEnabled()) {
750 logger.debug("Caught exception ", e);
752 //there is no way to identify if document does not exist due to
753 //lack of typed exception for getDocument method
756 if (repoSession != null) {
757 releaseRepositorySession(repoSession);
764 * @see org.collectionspace.services.common.repository.RepositoryClient#createWorkspace(java.lang.String, java.lang.String)
767 public String createWorkspace(String domainName, String workspaceName) throws Exception {
768 RepositoryInstance repoSession = null;
769 String workspaceId = null;
771 repoSession = getRepositorySession();
772 DocumentRef parentDocRef = new PathRef(
774 + "/" + "workspaces");
775 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
776 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
777 workspaceName, "Workspace");
778 doc.setPropertyValue("dc:title", workspaceName);
779 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
781 doc = repoSession.createDocument(doc);
782 workspaceId = doc.getId();
784 if (logger.isDebugEnabled()) {
785 logger.debug("created workspace name=" + workspaceName
786 + " id=" + workspaceId);
788 } catch (Exception e) {
789 if (logger.isDebugEnabled()) {
790 logger.debug("createWorkspace caught exception ", e);
794 if (repoSession != null) {
795 releaseRepositorySession(repoSession);
802 * @see org.collectionspace.services.common.repository.RepositoryClient#getWorkspaceId(java.lang.String, java.lang.String)
805 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
806 String workspaceId = null;
807 RepositoryInstance repoSession = null;
809 repoSession = getRepositorySession();
810 DocumentRef docRef = new PathRef(
813 + "/" + workspaceName);
814 DocumentModel workspace = repoSession.getDocument(docRef);
815 workspaceId = workspace.getId();
816 } catch (DocumentException de) {
818 } catch (Exception e) {
819 if (logger.isDebugEnabled()) {
820 logger.debug("Caught exception ", e);
822 throw new DocumentException(e);
824 if (repoSession != null) {
825 releaseRepositorySession(repoSession);
832 * Append a WHERE clause to the NXQL query.
834 * @param query The NXQL query to which the WHERE clause will be appended.
835 * @param querycontext The query context, which provides the WHERE clause to append.
837 private final void appendNXQLWhere(StringBuilder query, QueryContext queryContext) {
839 // Restrict search to a specific Nuxeo domain
840 // TODO This is a slow method for tenant-filter
841 // We should make this a property that is indexed.
843 // query.append(" WHERE ecm:path STARTSWITH '/" + queryContext.domain + "'");
846 // Restrict search to the current tenant ID. Is the domain path filter (above) still needed?
848 query.append(/*IQueryManager.SEARCH_QUALIFIER_AND +*/ " WHERE " + DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA + ":"
849 + DocumentModelHandler.COLLECTIONSPACE_CORE_TENANTID
850 + " = " + queryContext.getTenantId());
852 // Finally, append the incoming where clause
854 String whereClause = queryContext.getWhereClause();
855 if (whereClause != null && ! whereClause.trim().isEmpty()) {
856 // Due to an apparent bug/issue in how Nuxeo translates the NXQL query string
857 // into SQL, we need to parenthesize our 'where' clause
858 query.append(IQueryManager.SEARCH_QUALIFIER_AND + "(" + whereClause + ")");
861 // Please lookup this use in Nuxeo support and document here
863 query.append(IQueryManager.SEARCH_QUALIFIER_AND + "ecm:isProxy = 0");
867 * Append an ORDER BY clause to the NXQL query.
869 * @param query The NXQL query to which the ORDER BY clause will be appended.
870 * @param querycontext The query context, which provides the ORDER BY clause to append.
872 private final void appendNXQLOrderBy(StringBuilder query, QueryContext queryContext) {
873 // Append the incoming ORDER BY clause
874 String orderByClause = queryContext.getOrderByClause();
875 if (orderByClause != null && ! orderByClause.trim().isEmpty()) {
876 // FIXME Verify whether enclosing parentheses may be required, and add
877 // them if so, as is being done in appendNXQLWhere.
878 query.append(" ORDER BY ");
879 query.append(orderByClause);
882 // FIXME Determine where and how to handle ASC[ending] and DESC[ending] qualifiers:
884 // Will these be included in the value of the relevant 'order by' query param?
886 // Will the format of the order by clause be verified, including placement of
887 // the 'order by' qualifiers?
892 * Builds an NXQL SELECT query for a single document type.
894 * @param queryContext The query context
895 * @return an NXQL query
897 private final String buildNXQLQuery(QueryContext queryContext) {
898 StringBuilder query = new StringBuilder("SELECT * FROM ");
899 query.append(queryContext.getDocType());
900 appendNXQLWhere(query, queryContext);
901 appendNXQLOrderBy(query, queryContext);
902 return query.toString();
906 * Builds an NXQL SELECT query across multiple document types.
908 * @param docTypes a list of document types to be queried
909 * @param queryContext the query context
910 * @return an NXQL query
912 private final String buildNXQLQuery(List<String> docTypes, QueryContext queryContext) {
913 StringBuilder query = new StringBuilder("SELECT * FROM ");
914 boolean fFirst = true;
915 for (String docType : docTypes) {
921 query.append(docType);
923 appendNXQLWhere(query, queryContext);
924 // FIXME add 'order by' clause here, if appropriate
925 return query.toString();
929 * Gets the repository session.
931 * @return the repository session
932 * @throws Exception the exception
934 private RepositoryInstance getRepositorySession() throws Exception {
935 // FIXME: is it possible to reuse repository session?
936 // Authentication failures happen while trying to reuse the session
937 Profiler profiler = new Profiler("getRepositorySession():", 2);
939 NuxeoClient client = NuxeoConnector.getInstance().getClient();
940 RepositoryInstance repoSession = client.openRepository();
941 if (logger.isTraceEnabled()) {
942 logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
949 * Release repository session.
951 * @param repoSession the repo session
953 private void releaseRepositorySession(RepositoryInstance repoSession) {
955 NuxeoClient client = NuxeoConnector.getInstance().getClient();
957 client.releaseRepository(repoSession);
958 } catch (Exception e) {
959 logger.error("Could not close the repository session", e);
960 // no need to throw this service specific exception