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;
26 import org.collectionspace.services.common.document.BadRequestException;
27 import org.collectionspace.services.common.document.DocumentException;
28 import org.collectionspace.services.common.document.DocumentFilter;
29 import org.collectionspace.services.common.document.DocumentHandler;
30 import org.collectionspace.services.common.document.DocumentNotFoundException;
31 import org.collectionspace.services.common.document.DocumentHandler.Action;
32 import org.collectionspace.services.common.document.DocumentWrapper;
33 import org.collectionspace.services.common.document.DocumentWrapperImpl;
35 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
36 import org.collectionspace.services.common.query.IQueryManager;
37 import org.collectionspace.services.common.repository.RepositoryClient;
39 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
40 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
41 import org.nuxeo.common.utils.IdUtils;
42 import org.nuxeo.ecm.core.api.ClientException;
43 import org.nuxeo.ecm.core.api.DocumentModel;
44 import org.nuxeo.ecm.core.api.DocumentModelList;
45 import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
46 import org.nuxeo.ecm.core.api.DocumentRef;
47 import org.nuxeo.ecm.core.api.IdRef;
48 import org.nuxeo.ecm.core.api.PathRef;
49 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
50 import org.nuxeo.ecm.core.client.NuxeoClient;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
56 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
57 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
60 * $LastChangedRevision: $ $LastChangedDate: $
62 public class RepositoryJavaClientImpl implements RepositoryClient {
65 * The Class QueryContext.
67 private class QueryContext {
71 /** The doc filter. */
72 DocumentFilter docFilter;
73 /** The where clause. */
75 /** The order by clause. */
83 * Instantiates a new query context.
86 * @throws DocumentNotFoundException the document not found exception
87 * @throws DocumentException the document exception
89 QueryContext(ServiceContext<MultipartInput, MultipartOutput> ctx) throws DocumentNotFoundException, DocumentException {
90 docType = ctx.getDocumentType();
91 if (docType == null) {
92 throw new DocumentNotFoundException(
93 "Unable to find DocumentType for service " + ctx.getServiceName());
95 domain = ctx.getRepositoryDomainName();
97 throw new DocumentNotFoundException(
98 "Unable to find Domain for service " + ctx.getServiceName());
100 tenantId = ctx.getTenantId();
101 if (tenantId == null) {
102 throw new IllegalArgumentException(
103 "Service context has no Tenant ID specified.");
108 * Instantiates a new query context.
111 * @param theWhereClause the where clause
112 * @throws DocumentNotFoundException the document not found exception
113 * @throws DocumentException the document exception
115 QueryContext(ServiceContext<MultipartInput, MultipartOutput> ctx,
116 String theWhereClause) throws DocumentNotFoundException, DocumentException {
118 whereClause = theWhereClause;
122 * Instantiates a new query context.
125 * @param handler the handler
126 * @throws DocumentNotFoundException the document not found exception
127 * @throws DocumentException the document exception
129 QueryContext(ServiceContext<MultipartInput, MultipartOutput> ctx,
130 DocumentHandler handler) throws DocumentNotFoundException, DocumentException {
132 if (handler == null) {
133 throw new IllegalArgumentException(
134 "Document handler is missing.");
136 docFilter = handler.getDocumentFilter();
137 if (docFilter == null) {
138 throw new IllegalArgumentException(
139 "Document handler has no Filter specified.");
141 whereClause = docFilter.getWhereClause();
142 orderByClause = docFilter.getOrderByClause();
146 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class);
149 * Instantiates a new repository java client impl.
151 public RepositoryJavaClientImpl() {
156 * Sets the collection space core values.
159 * @param documentModel the document model
160 * @throws ClientException the client exception
162 private void setCollectionSpaceCoreValues(ServiceContext<MultipartInput, MultipartOutput> ctx,
163 DocumentModel documentModel,
164 Action action) throws ClientException {
166 // Add the tenant ID value to the new entity
168 documentModel.setProperty(DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA,
169 DocumentModelHandler.COLLECTIONSPACE_CORE_TENANTID,
173 //add creation date value
183 * create document in the Nuxeo repository
185 * @param ctx service context under which this method is invoked
187 * of the document created
189 * should be used by the caller to provide and transform the
191 * @return id in repository of the newly created document
192 * @throws DocumentException
195 public String create(ServiceContext ctx,
196 DocumentHandler handler) throws BadRequestException,
199 if (ctx.getDocumentType() == null) {
200 throw new IllegalArgumentException(
201 "RepositoryJavaClient.create: docType is missing");
203 if (handler == null) {
204 throw new IllegalArgumentException(
205 "RepositoryJavaClient.create: handler is missing");
207 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
208 if (nuxeoWspaceId == null) {
209 throw new DocumentNotFoundException(
210 "Unable to find workspace for service " + ctx.getServiceName()
211 + " check if the workspace exists in the Nuxeo repository");
213 RepositoryInstance repoSession = null;
215 handler.prepare(Action.CREATE);
216 repoSession = getRepositorySession();
217 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
218 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
219 String wspacePath = wspaceDoc.getPathAsString();
220 //give our own ID so PathRef could be constructed later on
221 String id = IdUtils.generateId(UUID.randomUUID().toString());
222 // create document model
223 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id,
224 ctx.getDocumentType());
225 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
226 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
227 handler.handle(Action.CREATE, wrapDoc);
228 // create document with documentmodel
229 setCollectionSpaceCoreValues(ctx, doc, Action.CREATE);
230 doc = repoSession.createDocument(doc);
232 // TODO for sub-docs need to call into the handler to let it deal with subitems. Pass in the id,
233 // and assume the handler has the state it needs (doc fragments).
234 handler.complete(Action.CREATE, wrapDoc);
236 } catch (BadRequestException bre) {
238 } catch (Exception e) {
239 if (logger.isDebugEnabled()) {
240 logger.debug("Caught exception ", e);
242 throw new DocumentException(e);
244 if (repoSession != null) {
245 releaseRepositorySession(repoSession);
252 * get document from the Nuxeo repository
253 * @param ctx service context under which this method is invoked
255 * of the document to retrieve
257 * should be used by the caller to provide and transform the
259 * @throws DocumentException
262 public void get(ServiceContext ctx, String id, DocumentHandler handler)
263 throws DocumentNotFoundException, DocumentException {
265 if (handler == null) {
266 throw new IllegalArgumentException(
267 "RepositoryJavaClient.get: handler is missing");
269 RepositoryInstance repoSession = null;
272 handler.prepare(Action.GET);
273 repoSession = getRepositorySession();
274 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
275 DocumentModel doc = null;
277 doc = repoSession.getDocument(docRef);
278 } catch (ClientException ce) {
279 String msg = "could not find document with id=" + id;
280 logger.error(msg, ce);
281 throw new DocumentNotFoundException(msg, ce);
283 //set reposession to handle the document
284 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
285 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
286 handler.handle(Action.GET, wrapDoc);
287 handler.complete(Action.GET, wrapDoc);
288 } catch (IllegalArgumentException iae) {
290 } catch (DocumentException de) {
292 } catch (Exception e) {
293 if (logger.isDebugEnabled()) {
294 logger.debug("Caught exception ", e);
296 throw new DocumentException(e);
298 if (repoSession != null) {
299 releaseRepositorySession(repoSession);
305 * get document from the Nuxeo repository, using the docFilter params.
306 * @param ctx service context under which this method is invoked
308 * should be used by the caller to provide and transform the
309 * document. Handler must have a docFilter set to return a single item.
310 * @throws DocumentException
313 public void get(ServiceContext ctx, DocumentHandler handler)
314 throws DocumentNotFoundException, DocumentException {
315 QueryContext queryContext = new QueryContext(ctx, handler);
316 RepositoryInstance repoSession = null;
319 handler.prepare(Action.GET);
320 repoSession = getRepositorySession();
322 DocumentModelList docList = null;
323 // force limit to 1, and ignore totalSize
324 String query = buildNXQLQuery(queryContext);
325 docList = repoSession.query(query, null, 1, 0, false);
326 if (docList.size() != 1) {
327 throw new DocumentNotFoundException("No document found matching filter params.");
329 DocumentModel doc = docList.get(0);
331 if (logger.isDebugEnabled()) {
332 logger.debug("Executed NXQL query: " + query);
335 //set reposession to handle the document
336 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
337 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
338 handler.handle(Action.GET, wrapDoc);
339 handler.complete(Action.GET, wrapDoc);
340 } catch (IllegalArgumentException iae) {
342 } catch (DocumentException de) {
344 } catch (Exception e) {
345 if (logger.isDebugEnabled()) {
346 logger.debug("Caught exception ", e);
348 throw new DocumentException(e);
350 if (repoSession != null) {
351 releaseRepositorySession(repoSession);
357 * get wrapped documentModel from the Nuxeo repository
358 * @param ctx service context under which this method is invoked
360 * of the document to retrieve
361 * @throws DocumentException
364 public DocumentWrapper<DocumentModel> getDoc(
365 ServiceContext ctx, String id)
366 throws DocumentNotFoundException, DocumentException {
367 RepositoryInstance repoSession = null;
368 DocumentWrapper<DocumentModel> wrapDoc = null;
371 repoSession = getRepositorySession();
372 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
373 DocumentModel doc = null;
375 doc = repoSession.getDocument(docRef);
376 } catch (ClientException ce) {
377 String msg = "could not find document with id=" + id;
378 logger.error(msg, ce);
379 throw new DocumentNotFoundException(msg, ce);
381 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
382 } catch (IllegalArgumentException iae) {
384 } catch (DocumentException de) {
386 } catch (Exception e) {
387 if (logger.isDebugEnabled()) {
388 logger.debug("Caught exception ", e);
390 throw new DocumentException(e);
392 if (repoSession != null) {
393 releaseRepositorySession(repoSession);
400 * find wrapped documentModel from the Nuxeo repository
401 * @param ctx service context under which this method is invoked
402 * @param where NXQL where clause to get the document
403 * @throws DocumentException
406 public DocumentWrapper<DocumentModel> findDoc(
407 ServiceContext ctx, String whereClause)
408 throws DocumentNotFoundException, DocumentException {
409 RepositoryInstance repoSession = null;
410 DocumentWrapper<DocumentModel> wrapDoc = null;
413 QueryContext queryContext = new QueryContext(ctx, whereClause);
414 repoSession = getRepositorySession();
415 DocumentModelList docList = null;
416 // force limit to 1, and ignore totalSize
417 String query = buildNXQLQuery(queryContext);
418 docList = repoSession.query(query,
423 if (docList.size() != 1) {
424 if (logger.isDebugEnabled()) {
425 logger.debug("findDoc: Query found: " + docList.size() + " items.");
426 logger.debug(" Query: " + query);
428 throw new DocumentNotFoundException("No document found matching filter params.");
430 DocumentModel doc = docList.get(0);
431 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
432 } catch (IllegalArgumentException iae) {
434 } catch (DocumentException de) {
436 } catch (Exception e) {
437 if (logger.isDebugEnabled()) {
438 logger.debug("Caught exception ", e);
440 throw new DocumentException(e);
442 if (repoSession != null) {
443 releaseRepositorySession(repoSession);
450 * find doc and return CSID from the Nuxeo repository
451 * @param ctx service context under which this method is invoked
452 * @param where NXQL where clause to get the document
453 * @throws DocumentException
456 public String findDocCSID(
457 ServiceContext ctx, String whereClause)
458 throws DocumentNotFoundException, DocumentException {
461 DocumentWrapper<DocumentModel> wrapDoc = findDoc(ctx, whereClause);
462 DocumentModel docModel = wrapDoc.getWrappedObject();
463 csid = NuxeoUtils.extractId(docModel.getPathAsString());
464 } catch (DocumentNotFoundException dnfe) {
466 } catch (IllegalArgumentException iae) {
468 } catch (DocumentException de) {
470 } catch (Exception e) {
471 if (logger.isDebugEnabled()) {
472 logger.debug("Caught exception ", e);
474 throw new DocumentException(e);
480 * Find a list of documentModels from the Nuxeo repository
481 * @param docTypes a list of DocType names to match
482 * @param where the clause to qualify on
483 * @param domain the domain for the associated services
487 public DocumentWrapper<DocumentModelList> findDocs(
489 List<String> docTypes,
491 int pageSize, int pageNum, boolean computeTotal)
492 throws DocumentNotFoundException, DocumentException {
493 RepositoryInstance repoSession = null;
494 DocumentWrapper<DocumentModelList> wrapDoc = null;
497 if (docTypes == null || docTypes.size() < 1) {
498 throw new DocumentNotFoundException(
499 "findDocs must specify at least one DocumentType.");
501 repoSession = getRepositorySession();
502 DocumentModelList docList = null;
503 // force limit to 1, and ignore totalSize
504 QueryContext queryContext = new QueryContext(ctx, whereClause);
505 String query = buildNXQLQuery(docTypes, queryContext);
506 docList = repoSession.query(query, null, pageSize, pageNum, computeTotal);
507 wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
508 } catch (IllegalArgumentException iae) {
510 } catch (Exception e) {
511 if (logger.isDebugEnabled()) {
512 logger.debug("Caught exception ", e);
514 throw new DocumentException(e);
516 if (repoSession != null) {
517 releaseRepositorySession(repoSession);
524 * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.util.List, org.collectionspace.services.common.document.DocumentHandler)
527 public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
528 throws DocumentNotFoundException, DocumentException {
529 if (handler == null) {
530 throw new IllegalArgumentException(
531 "RepositoryJavaClient.getAll: handler is missing");
534 RepositoryInstance repoSession = null;
537 handler.prepare(Action.GET_ALL);
538 repoSession = getRepositorySession();
539 DocumentModelList docModelList = new DocumentModelListImpl();
540 //FIXME: Should be using NuxeoUtils.createPathRef for security reasons
541 for (String csid : csidList) {
542 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
543 DocumentModel docModel = repoSession.getDocument(docRef);
544 docModelList.add(docModel);
547 //set reposession to handle the document
548 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
549 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docModelList);
550 handler.handle(Action.GET_ALL, wrapDoc);
551 handler.complete(Action.GET_ALL, wrapDoc);
552 } catch (DocumentException de) {
554 } catch (Exception e) {
555 if (logger.isDebugEnabled()) {
556 logger.debug("Caught exception ", e);
558 throw new DocumentException(e);
560 if (repoSession != null) {
561 releaseRepositorySession(repoSession);
567 * getAll get all documents for an entity entity service from the Nuxeo
570 * @param ctx service context under which this method is invoked
572 * should be used by the caller to provide and transform the
574 * @throws DocumentException
577 public void getAll(ServiceContext ctx, DocumentHandler handler)
578 throws DocumentNotFoundException, DocumentException {
579 if (handler == null) {
580 throw new IllegalArgumentException(
581 "RepositoryJavaClient.getAll: handler is missing");
583 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
584 if (nuxeoWspaceId == null) {
585 throw new DocumentNotFoundException(
586 "Unable to find workspace for service "
587 + ctx.getServiceName()
588 + " check if the workspace exists in the Nuxeo repository");
590 RepositoryInstance repoSession = null;
593 handler.prepare(Action.GET_ALL);
594 repoSession = getRepositorySession();
595 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
596 DocumentModelList docList = repoSession.getChildren(wsDocRef);
597 //set reposession to handle the document
598 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
599 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
600 handler.handle(Action.GET_ALL, wrapDoc);
601 handler.complete(Action.GET_ALL, wrapDoc);
602 } catch (DocumentException de) {
604 } catch (Exception e) {
605 if (logger.isDebugEnabled()) {
606 logger.debug("Caught exception ", e);
608 throw new DocumentException(e);
610 if (repoSession != null) {
611 releaseRepositorySession(repoSession);
617 * getFiltered get all documents for an entity service from the Document repository,
618 * given filter parameters specified by the handler.
619 * @param ctx service context under which this method is invoked
620 * @param handler should be used by the caller to provide and transform the document
621 * @throws DocumentNotFoundException if workspace not found
622 * @throws DocumentException
625 public void getFiltered(ServiceContext ctx, DocumentHandler handler)
626 throws DocumentNotFoundException, DocumentException {
628 QueryContext queryContext = new QueryContext(ctx, handler);
630 RepositoryInstance repoSession = null;
632 handler.prepare(Action.GET_ALL);
633 repoSession = getRepositorySession();
634 DocumentModelList docList = null;
635 String query = buildNXQLQuery(queryContext);
637 if (logger.isDebugEnabled()) {
638 logger.debug("Executing NXQL query: " + query.toString());
641 // If we have limit and/or offset, then pass true to get totalSize
642 // in returned DocumentModelList.
643 if ((queryContext.docFilter.getOffset() > 0) || (queryContext.docFilter.getPageSize() > 0)) {
644 docList = repoSession.query(query, null,
645 queryContext.docFilter.getPageSize(), queryContext.docFilter.getOffset(), true);
647 docList = repoSession.query(query);
650 //set repoSession to handle the document
651 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
652 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
653 handler.handle(Action.GET_ALL, wrapDoc);
654 handler.complete(Action.GET_ALL, wrapDoc);
655 } catch (DocumentException de) {
657 } catch (Exception e) {
658 if (logger.isDebugEnabled()) {
659 logger.debug("Caught exception ", e);
661 throw new DocumentException(e);
663 if (repoSession != null) {
664 releaseRepositorySession(repoSession);
670 * update given document in the Nuxeo repository
672 * @param ctx service context under which this method is invoked
676 * should be used by the caller to provide and transform the
678 * @throws DocumentException
681 public void update(ServiceContext ctx, String id, DocumentHandler handler)
682 throws BadRequestException, DocumentNotFoundException,
684 if (handler == null) {
685 throw new IllegalArgumentException(
686 "RepositoryJavaClient.update: handler is missing");
688 RepositoryInstance repoSession = null;
690 handler.prepare(Action.UPDATE);
691 repoSession = getRepositorySession();
692 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
693 DocumentModel doc = null;
695 doc = repoSession.getDocument(docRef);
696 } catch (ClientException ce) {
697 String msg = "Could not find document to update with id=" + id;
698 logger.error(msg, ce);
699 throw new DocumentNotFoundException(msg, ce);
701 //set reposession to handle the document
702 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
703 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
704 handler.handle(Action.UPDATE, wrapDoc);
705 setCollectionSpaceCoreValues(ctx, doc, Action.CREATE);
706 repoSession.saveDocument(doc);
708 handler.complete(Action.UPDATE, wrapDoc);
709 } catch (BadRequestException bre) {
711 } catch (DocumentException de) {
713 } catch (Exception e) {
714 if (logger.isDebugEnabled()) {
715 logger.debug("Caught exception ", e);
717 throw new DocumentException(e);
719 if (repoSession != null) {
720 releaseRepositorySession(repoSession);
726 * delete a document from the Nuxeo repository
727 * @param ctx service context under which this method is invoked
730 * @throws DocumentException
733 public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
736 if (logger.isDebugEnabled()) {
737 logger.debug("deleting document with id=" + id);
739 RepositoryInstance repoSession = null;
741 repoSession = getRepositorySession();
742 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
744 repoSession.removeDocument(docRef);
745 } catch (ClientException ce) {
746 String msg = "could not find document to delete with id=" + id;
747 logger.error(msg, ce);
748 throw new DocumentNotFoundException(msg, ce);
751 } catch (DocumentException de) {
753 } catch (Exception e) {
754 if (logger.isDebugEnabled()) {
755 logger.debug("Caught exception ", e);
757 throw new DocumentException(e);
759 if (repoSession != null) {
760 releaseRepositorySession(repoSession);
766 * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
769 public void delete(ServiceContext ctx, String id, DocumentHandler handler)
770 throws DocumentNotFoundException, DocumentException {
771 throw new UnsupportedOperationException();
775 public Hashtable<String, String> retrieveWorkspaceIds(String domainName) throws Exception {
776 return NuxeoConnector.getInstance().retrieveWorkspaceIds(domainName);
780 public String createDomain(String domainName) throws Exception {
781 RepositoryInstance repoSession = null;
782 String domainId = null;
784 repoSession = getRepositorySession();
785 DocumentRef parentDocRef = new PathRef("/");
786 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
787 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
788 domainName, "Domain");
789 doc.setPropertyValue("dc:title", domainName);
790 doc.setPropertyValue("dc:description", "A CollectionSpace domain "
792 doc = repoSession.createDocument(doc);
793 domainId = doc.getId();
795 if (logger.isDebugEnabled()) {
796 logger.debug("created tenant domain name=" + domainName
797 + " id=" + domainId);
799 } catch (Exception e) {
800 if (logger.isDebugEnabled()) {
801 logger.debug("createTenantSpace caught exception ", e);
805 if (repoSession != null) {
806 releaseRepositorySession(repoSession);
813 public String getDomainId(String domainName) throws Exception {
814 String domainId = null;
815 RepositoryInstance repoSession = null;
817 repoSession = getRepositorySession();
818 DocumentRef docRef = new PathRef(
820 DocumentModel domain = repoSession.getDocument(docRef);
821 domainId = domain.getId();
822 } catch (Exception e) {
823 if (logger.isDebugEnabled()) {
824 logger.debug("Caught exception ", e);
826 //there is no way to identify if document does not exist due to
827 //lack of typed exception for getDocument method
830 if (repoSession != null) {
831 releaseRepositorySession(repoSession);
838 * @see org.collectionspace.services.common.repository.RepositoryClient#createWorkspace(java.lang.String, java.lang.String)
841 public String createWorkspace(String domainName, String workspaceName) throws Exception {
842 RepositoryInstance repoSession = null;
843 String workspaceId = null;
845 repoSession = getRepositorySession();
846 DocumentRef parentDocRef = new PathRef(
848 + "/" + "workspaces");
849 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
850 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
851 workspaceName, "Workspace");
852 doc.setPropertyValue("dc:title", workspaceName);
853 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
855 doc = repoSession.createDocument(doc);
856 workspaceId = doc.getId();
858 if (logger.isDebugEnabled()) {
859 logger.debug("created workspace name=" + workspaceName
860 + " id=" + workspaceId);
862 } catch (Exception e) {
863 if (logger.isDebugEnabled()) {
864 logger.debug("createWorkspace caught exception ", e);
868 if (repoSession != null) {
869 releaseRepositorySession(repoSession);
876 * @see org.collectionspace.services.common.repository.RepositoryClient#getWorkspaceId(java.lang.String, java.lang.String)
879 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
880 String workspaceId = null;
881 RepositoryInstance repoSession = null;
883 repoSession = getRepositorySession();
884 DocumentRef docRef = new PathRef(
887 + "/" + workspaceName);
888 DocumentModel workspace = repoSession.getDocument(docRef);
889 workspaceId = workspace.getId();
890 } catch (DocumentException de) {
892 } catch (Exception e) {
893 if (logger.isDebugEnabled()) {
894 logger.debug("Caught exception ", e);
896 throw new DocumentException(e);
898 if (repoSession != null) {
899 releaseRepositorySession(repoSession);
906 * Append a WHERE clause to the NXQL query.
908 * @param query The NXQL query to which the WHERE clause will be appended.
909 * @param querycontext The query context, which provides the WHERE clause to append.
911 private final void appendNXQLWhere(StringBuilder query, QueryContext queryContext) {
913 // Restrict search to a specific Nuxeo domain
914 // TODO This is a slow method for tenant-filter
915 // We should make this a property that is indexed.
917 query.append(" WHERE ecm:path STARTSWITH '/" + queryContext.domain + "'");
920 // Restrict search to the current tenant ID. Is the domain path filter (above) still needed?
922 query.append(IQueryManager.SEARCH_QUALIFIER_AND + DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA + ":"
923 + DocumentModelHandler.COLLECTIONSPACE_CORE_TENANTID
924 + " = " + queryContext.tenantId);
926 // Finally, append the incoming where clause
928 String whereClause = queryContext.whereClause;
929 if (whereClause != null && ! whereClause.trim().isEmpty()) {
930 // Due to an apparent bug/issue in how Nuxeo translates the NXQL query string
931 // into SQL, we need to parenthesize our 'where' clause
932 query.append(IQueryManager.SEARCH_QUALIFIER_AND + "(" + whereClause + ")");
935 // Please lookup this use in Nuxeo support and document here
937 query.append(IQueryManager.SEARCH_QUALIFIER_AND + "ecm:isProxy = 0");
941 * Append an ORDER BY clause to the NXQL query.
943 * @param query The NXQL query to which the ORDER BY clause will be appended.
944 * @param querycontext The query context, which provides the ORDER BY clause to append.
946 private final void appendNXQLOrderBy(StringBuilder query, QueryContext queryContext) {
947 // Append the incoming ORDER BY clause
948 String orderByClause = queryContext.orderByClause;
949 if (orderByClause != null && ! orderByClause.trim().isEmpty()) {
950 // FIXME Verify whether enclosing parentheses may be required, and add
951 // them if so, as is being done in appendNXQLWhere.
952 query.append(" ORDER BY ");
953 query.append(orderByClause);
956 // FIXME Determine where and how to handle ASC[ending] and DESC[ending] qualifiers:
958 // Will these be included in the value of the relevant 'order by' query param?
960 // Will the format of the order by clause be verified, including placement of
961 // the 'order by' qualifiers?
966 * Builds an NXQL SELECT query for a single document type.
968 * @param queryContext The query context
969 * @return an NXQL query
971 private final String buildNXQLQuery(QueryContext queryContext) {
972 StringBuilder query = new StringBuilder("SELECT * FROM ");
973 query.append(queryContext.docType);
974 appendNXQLWhere(query, queryContext);
975 appendNXQLOrderBy(query, queryContext);
976 return query.toString();
980 * Builds an NXQL SELECT query across multiple document types.
982 * @param docTypes a list of document types to be queried
983 * @param queryContext the query context
984 * @return an NXQL query
986 private final String buildNXQLQuery(List<String> docTypes, QueryContext queryContext) {
987 StringBuilder query = new StringBuilder("SELECT * FROM ");
988 boolean fFirst = true;
989 for (String docType : docTypes) {
995 query.append(docType);
997 appendNXQLWhere(query, queryContext);
998 // FIXME add 'order by' clause here, if appropriate
999 return query.toString();
1003 * Gets the repository session.
1005 * @return the repository session
1006 * @throws Exception the exception
1008 private RepositoryInstance getRepositorySession() throws Exception {
1009 // FIXME: is it possible to reuse repository session?
1010 // Authentication failures happen while trying to reuse the session
1011 NuxeoClient client = NuxeoConnector.getInstance().getClient();
1012 RepositoryInstance repoSession = client.openRepository();
1013 if (logger.isDebugEnabled()) {
1014 logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
1020 * Release repository session.
1022 * @param repoSession the repo session
1024 private void releaseRepositorySession(RepositoryInstance repoSession) {
1026 NuxeoClient client = NuxeoConnector.getInstance().getClient();
1028 client.releaseRepository(repoSession);
1029 } catch (Exception e) {
1030 logger.error("Could not close the repository session", e);
1031 // no need to throw this service specific exception