001/*
002 * (C) Copyright 2006-2017 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Bogdan Stefanescu
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.core.api;
021
022import java.io.Serializable;
023import java.time.ZonedDateTime;
024import java.util.Arrays;
025import java.util.Calendar;
026import java.util.Collection;
027import java.util.GregorianCalendar;
028import java.util.List;
029import java.util.Map;
030import java.util.function.Function;
031
032import org.nuxeo.ecm.core.api.DocumentModel.DocumentModelRefresh;
033import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
034import org.nuxeo.ecm.core.api.security.ACE;
035import org.nuxeo.ecm.core.api.security.ACP;
036import org.nuxeo.ecm.core.schema.DocumentType;
037import org.nuxeo.ecm.core.schema.types.Schema;
038
039/**
040 * A session to the Nuxeo Core.
041 *
042 * @see DocumentModel
043 * @see DocumentRef
044 * @author Bogdan Stefanescu
045 * @author Florent Guillaume
046 */
047public interface CoreSession {
048
049    // used to pass properties to importDocument
050    String IMPORT_VERSION_VERSIONABLE_ID = "ecm:versionableId";
051
052    String IMPORT_VERSION_CREATED = "ecm:versionCreated";
053
054    String IMPORT_VERSION_LABEL = "ecm:versionLabel";
055
056    String IMPORT_VERSION_DESCRIPTION = "ecm:versionDescription";
057
058    String IMPORT_VERSION_IS_LATEST = "ecm:isLatestVersion";
059
060    String IMPORT_VERSION_IS_LATEST_MAJOR = "ecm:isLatestMajorVersion";
061
062    String IMPORT_IS_VERSION = "ecm:isVersion";
063
064    String IMPORT_VERSION_MAJOR = "ecm:majorVersion";
065
066    String IMPORT_VERSION_MINOR = "ecm:minorVersion";
067
068    /** @since 11.1 */
069    String IMPORT_IS_RECORD = "ecm:isRecord";
070
071    /** @since 11.1 */
072    String IMPORT_RETAIN_UNTIL = "ecm:retainUntil";
073
074    /** @since 11.1 */
075    String IMPORT_HAS_LEGAL_HOLD = "ecm:hasLegalHold";
076
077    /** @deprecated since 11.1 */
078    @Deprecated
079    String IMPORT_IS_RETENTION_ACTIVE = "ecm:isRetentionActive";
080
081    String IMPORT_PROXY_TARGET_ID = "ecm:proxyTargetId";
082
083    String IMPORT_PROXY_VERSIONABLE_ID = "ecm:proxyVersionableId";
084
085    String IMPORT_LIFECYCLE_POLICY = "ecm:lifeCyclePolicy";
086
087    String IMPORT_LIFECYCLE_STATE = "ecm:lifeCycleState";
088
089    /** @since 5.4.2 */
090    String IMPORT_LOCK_OWNER = "ecm:lockOwner";
091
092    /**
093     * Lock creation time as a Calendar object.
094     *
095     * @since 5.4.2
096     */
097    String IMPORT_LOCK_CREATED = "ecm:lockCreated";
098
099    String IMPORT_CHECKED_IN = "ecm:isCheckedIn";
100
101    String IMPORT_BASE_VERSION_ID = "ecm:baseVersionId";
102
103    /** The document type to use to create a proxy by import. */
104    String IMPORT_PROXY_TYPE = "ecm:proxy";
105
106    /**
107     * Skip the check to see if a destination exists on importDocument and createDocument
108     *
109     * @since 9.1
110     **/
111    String SKIP_DESTINATION_CHECK_ON_CREATE = "skipDestinationCheck";
112
113    /**
114     * Allow version write, Boolean parameter passed in context data at saveDocument time.
115     *
116     * @since 5.9.2
117     */
118    String ALLOW_VERSION_WRITE = "allowVersionWrite";
119
120    /**
121     * A context data key which represents the source of current session calls. For example:
122     * <ul>
123     * <li>fileimporter-NoteImporter</li>
124     * <li>drive</li>
125     * <li>rest</li>
126     * </ul>
127     *
128     * @since 9.1
129     */
130    String SOURCE = "source";
131
132    /**
133     * Change token, a String parameter passed in context data at {@link #saveDocument} time.
134     *
135     * @see DocumentModel#putContextData
136     * @see #getChangeToken
137     * @see DocumentModel#getChangeToken
138     * @since 9.1
139     */
140    String CHANGE_TOKEN = "changeToken";
141
142    /**
143     * User change, a Boolean parameter passed in context data at {@link #saveDocument} time.
144     * <p>
145     * When {@linkplain Boolean#TRUE TRUE}, it marks the document as being modified by a user change. This causes an
146     * additional change token increment and check during save.
147     *
148     * @since 9.2
149     */
150    String USER_CHANGE = "userChange";
151
152    /**
153     * Does nothing.
154     *
155     * @since 5.9.3
156     * @deprecated since 10.1
157     */
158    @Deprecated
159    void close();
160
161    /**
162     * Gets the document type object given its type name.
163     *
164     * @param type the document type name
165     * @return the type the doc type object
166     */
167    DocumentType getDocumentType(String type);
168
169    /**
170     * Cancels any pending change made through this session.
171     */
172    void cancel();
173
174    /**
175     * Saves any pending changes done until now through this session.
176     */
177    void save();
178
179    /**
180     * Returns the repository name and principal.
181     *
182     * @return the repository name and principal
183     * @deprecated since 11.1
184     */
185    @Deprecated
186    String getSessionId();
187
188    /**
189     * Returns {@code true} if all sessions in the current thread share the same state.
190     *
191     * @deprecated since 8.4 as it always returns true by design
192     */
193    @Deprecated
194    boolean isStateSharedByAllThreadSessions();
195
196    /**
197     * Gets the principal that created the client session.
198     *
199     * @return the principal
200     */
201    NuxeoPrincipal getPrincipal();
202
203    /**
204     * Checks if the principal that created the client session has the given privilege on the referred document.
205     */
206    boolean hasPermission(DocumentRef docRef, String permission);
207
208    /**
209     * Checks if a given principal has the given privilege on the referred document.
210     */
211    boolean hasPermission(NuxeoPrincipal principal, DocumentRef docRef, String permission);
212
213    /**
214     * Filters the supplied permissions based on whether they are granted to a given principal for a given document.
215     *
216     * @since 9.1
217     */
218    Collection<String> filterGrantedPermissions(NuxeoPrincipal principal, DocumentRef docRef,
219            Collection<String> permissions);
220
221    /**
222     * Gets the root document of this repository.
223     *
224     * @return the root document. cannot be null
225     */
226    DocumentModel getRootDocument();
227
228    /**
229     * Gets a document model given its reference.
230     * <p>
231     * The default schemas are used to populate the returned document model. Default schemas are configured via the
232     * document type manager.
233     * <p>
234     * Any other data model not part of the default schemas will be lazily loaded as needed.
235     *
236     * @param docRef the document reference
237     * @return the document
238     * @throws DocumentNotFoundException if the document cannot be found
239     */
240    DocumentModel getDocument(DocumentRef docRef) throws DocumentNotFoundException;
241
242    /**
243     * Gets a list of documents given their references.
244     * <p>
245     * Documents that are not accessible are skipped.
246     *
247     * @throws DocumentNotFoundException if a document cannot be found
248     */
249    DocumentModelList getDocuments(DocumentRef[] docRefs) throws DocumentNotFoundException;
250
251    /**
252     * Gets a child document given its name and the parent reference.
253     * <p>
254     * Throws an exception if the document could not be found.
255     * <p>
256     * If the supplied id is null, returns the default child of the document if any, otherwise raises an exception.
257     * <p>
258     * If the parent is null or its path is null, then root is considered.
259     *
260     * @param parent the reference to the parent document
261     * @param name the name of the child document to retrieve
262     * @return the named child if exists
263     * @throws DocumentNotFoundException if there is no child with the given name
264     */
265    DocumentModel getChild(DocumentRef parent, String name);
266
267    /**
268     * Tests if the document has a child with the given name.
269     * <p>
270     * This operation silently ignores non-folder documents: If the document is not a folder then returns false.
271     *
272     * @param parent the document
273     * @param name the child name
274     * @return {@code true} if the document has a child with the given name
275     * @since 7.3
276     */
277    boolean hasChild(DocumentRef parent, String name);
278
279    /**
280     * Gets the children of the given parent.
281     *
282     * @param parent the parent reference
283     * @return the children if any, an empty list if no children or null if the specified parent document is not a
284     *         folder
285     */
286    DocumentModelList getChildren(DocumentRef parent);
287
288    /**
289     * Gets an iterator to the children of the given parent.
290     *
291     * @param parent the parent reference
292     * @return iterator over the children collection or null if the specified parent document is not a folder
293     */
294    DocumentModelIterator getChildrenIterator(DocumentRef parent);
295
296    /**
297     * Gets the children of the given parent filtered according to the given document type.
298     *
299     * @param parent the parent reference
300     * @param type the wanted document type
301     * @return the documents if any, an empty list if none were found or null if the parent document is not a folder
302     */
303    DocumentModelList getChildren(DocumentRef parent, String type);
304
305    /**
306     * Gets an iterator to the children of the given parent filtered according to the given document type.
307     */
308    DocumentModelIterator getChildrenIterator(DocumentRef parent, String type);
309
310    /**
311     * Gets the children of the given parent filtered according to the given document type and permission.
312     *
313     * @param parent the parent reference
314     * @param type the wanted document type
315     * @param perm the permission the user must have
316     * @return the documents if any, an empty list if none were found or null if the parent document is not a folder
317     */
318    DocumentModelList getChildren(DocumentRef parent, String type, String perm);
319
320    /**
321     * Same as {@link #getChildren(DocumentRef, String, String)} but the result is filtered and then sorted using the
322     * specified filter and sorter.
323     *
324     * @param parent the parent reference
325     * @param type the wanted type
326     * @param perm permission to check for. If null, defaults to READ
327     * @param filter the filter to use if any, null otherwise
328     * @param sorter the sorter to use if any, null otherwise
329     * @return the list of the children or an empty list if no children were found or null if the given parent is not a
330     *         folder
331     */
332    DocumentModelList getChildren(DocumentRef parent, String type, String perm, Filter filter, Sorter sorter);
333
334    /**
335     * Gets the references of the children. No permission is checked if perm is null.
336     *
337     * @param parentRef the parent reference
338     * @param perm the permission to check on the children (usually READ); if null, <b>no permission is checked</b>
339     * @return a list of children references
340     * @since 1.4.1
341     */
342    List<DocumentRef> getChildrenRefs(DocumentRef parentRef, String perm);
343
344    /**
345     * Gets the children of the given parent filtered according to the given document type and permission. Long result
346     * sets are loaded frame by frame transparently by the DocumentModelIterator.
347     */
348    DocumentModelIterator getChildrenIterator(DocumentRef parent, String type, String perm, Filter filter);
349
350    /**
351     * Same as {@link #getChildren(DocumentRef, String, String, Filter, Sorter)} without specific permission filtering.
352     *
353     * @param parent the parent reference
354     * @param type the wanted type
355     * @param filter the filter to use if any, null otherwise
356     * @param sorter the sorter to use if any, null otherwise
357     * @return the list of the children or an empty list if no children were found or null if the given parent is not a
358     *         folder
359     */
360    DocumentModelList getChildren(DocumentRef parent, String type, Filter filter, Sorter sorter);
361
362    /**
363     * Same as {@link CoreSession#getChildren(DocumentRef)} but returns only folder documents.
364     *
365     * @param parent the parent ref
366     * @return a list of children if any, an empty one if none or null if the given parent is not a folder
367     */
368    DocumentModelList getFolders(DocumentRef parent);
369
370    /**
371     * Same as {@link CoreSession#getFolders(DocumentRef)} but uses an optional filter and sorter on the result.
372     *
373     * @param parent the parent reference
374     * @param filter the filter to use or null if none
375     * @param sorter the sorter to use or null if none
376     * @return a list of children if any, an empty one if none or null if the given parent is not a folder
377     */
378    DocumentModelList getFolders(DocumentRef parent, Filter filter, Sorter sorter);
379
380    /**
381     * Same as {@link CoreSession#getChildren(DocumentRef)} but returns only non-folder documents.
382     *
383     * @param parent the parent reference
384     * @return a list of children if any, an empty one if none or null if the given parent is not a folder
385     */
386    DocumentModelList getFiles(DocumentRef parent);
387
388    /**
389     * Same as {@link #getFiles} but uses an optional filter and sorter on the result.
390     *
391     * @param parent the parent reference
392     * @param filter the filter to use or null if none
393     * @param sorter the sorter to use or null if none
394     * @return a list of children if any, an empty one if none or null if the given parent is not a folder
395     */
396    DocumentModelList getFiles(DocumentRef parent, Filter filter, Sorter sorter);
397
398    /**
399     * Returns the parent ref of the document referenced by {@code docRef} or {@code null} if this is the root document.
400     * <p>
401     * This method does not check the permissions on the parent document of this {@code CoreSession}'s {@code Principal}
402     * .
403     *
404     * @since 5.4.2
405     */
406    DocumentRef getParentDocumentRef(DocumentRef docRef);
407
408    /**
409     * Gets the parent document or null if this is the root document.
410     *
411     * @return the parent document or null if this is the root document
412     */
413    DocumentModel getParentDocument(DocumentRef docRef);
414
415    /**
416     * Gets the parent documents in path from the root to the given document or empty list if this is the root document.
417     * <p>
418     * Documents the principal is is not allowed to browse are filtered out the parents list.
419     *
420     * @return the list with parent documents or empty list if this is the root document
421     */
422    List<DocumentModel> getParentDocuments(DocumentRef docRef);
423
424    /**
425     * Tests if the document pointed by the given reference exists and is accessible.
426     * <p>
427     * This operation makes no difference between non-existence and permission problems.
428     * <p>
429     * If the parent is null or its path is null, then root is considered.
430     *
431     * @param docRef the reference to the document to test for existence
432     * @return true if the referenced document exists, false otherwise
433     */
434    boolean exists(DocumentRef docRef);
435
436    /**
437     * Tests if the document has any children.
438     * <p>
439     * This operation silently ignores non-folder documents: If the document is not a folder then returns false.
440     * <p>
441     * If the parent is null or its path is null, then root is considered.
442     *
443     * @param docRef the reference to the document to test
444     * @return true if document has children, false otherwise
445     */
446    boolean hasChildren(DocumentRef docRef);
447
448    /**
449     * Creates a document model using type name.
450     * <p>
451     * Used to fetch initial datamodels from the type definition.
452     * <p>
453     * DocumentModel creation notifies a {@link DocumentEventTypes#EMPTY_DOCUMENTMODEL_CREATED} so that core event
454     * listener can initialize its content with computed properties.
455     *
456     * @return the initial document model
457     */
458    DocumentModel createDocumentModel(String typeName);
459
460    /**
461     * Creates a document model using required information.
462     * <p>
463     * Used to fetch initial datamodels from the type definition.
464     * <p>
465     * DocumentModel creation notifies a {@link DocumentEventTypes#EMPTY_DOCUMENTMODEL_CREATED} so that core event
466     * listener can initialize its content with computed properties.
467     *
468     * @param parentPath the parent path
469     * @param name The destination name
470     * @param typeName the type name
471     * @return the initial document model
472     */
473    DocumentModel createDocumentModel(String parentPath, String name, String typeName);
474
475    /**
476     * Creates a new document model using required information.
477     * <p>
478     * Used to fetch initial datamodels from the type definition.
479     * <p>
480     * DocumentModel creation notifies a {@link DocumentEventTypes#EMPTY_DOCUMENTMODEL_CREATED} so that core event
481     * listener can initialize its content with computed properties.
482     *
483     * @param parentRef the parent document ref {@link DocumentRef}
484     * @param name The destination name
485     * @param typeName the type name
486     * @return the initial document model
487     * @since 11.1
488     */
489    DocumentModel newDocumentModel(DocumentRef parentRef, String name, String typeName);
490
491    /**
492     * Creates a document model using required information.
493     * <p>
494     * Used to fetch initial datamodels from the type definition.
495     * <p>
496     * DocumentModel creation notifies a {@link DocumentEventTypes#EMPTY_DOCUMENTMODEL_CREATED} so that core event
497     * listener can initialize its content with computed properties.
498     *
499     * @param typeName the type name
500     * @param options additional contextual data provided to core event listeners
501     * @return the initial document model
502     */
503    DocumentModel createDocumentModel(String typeName, Map<String, Object> options);
504
505    /**
506     * Creates a document using given document model for initialization.
507     * <p>
508     * The model contains path of the new document, its type and optionally the initial data models of the document.
509     * <p>
510     *
511     * @param model the document model to use for initialization
512     * @return the created document
513     */
514    DocumentModel createDocument(DocumentModel model);
515
516    /**
517     * Bulk creation of documents.
518     *
519     * @param docModels the document models to use for intialization
520     * @return the created documents
521     */
522    DocumentModel[] createDocument(DocumentModel[] docModels);
523
524    /**
525     * Low-level import of documents, reserved for the administrator.
526     * <p>
527     * This method is used to import documents with given ids, or directly import versions and proxies.
528     * <p>
529     * The id, parent, name and typeName must be present in each docModel.
530     * <p>
531     * The context data needs to be filled with values depending on the type of the document:
532     * <p>
533     * For a proxy (type = {@code "ecm:proxyType"}): {@link #IMPORT_PROXY_TARGET_ID} and
534     * {@link #IMPORT_PROXY_VERSIONABLE_ID}.
535     * <p>
536     * For a version (no parent): {@link #IMPORT_VERSION_VERSIONABLE_ID}, {@link #IMPORT_VERSION_CREATED},
537     * {@link #IMPORT_VERSION_LABEL} and {@link #IMPORT_VERSION_DESCRIPTION}.
538     * <p>
539     * For a live document: {@link #IMPORT_BASE_VERSION_ID} and {@link #IMPORT_CHECKED_IN} (Boolean).
540     * <p>
541     * For a live document or a version: {@link #IMPORT_LIFECYCLE_POLICY} , {@link #IMPORT_LIFECYCLE_STATE},
542     * {@link #IMPORT_VERSION_MAJOR} (Long) and {@link #IMPORT_VERSION_MINOR} (Long).
543     *
544     * @param docModels the documents to create
545     */
546    void importDocuments(List<DocumentModel> docModels);
547
548    /**
549     * Saves changes done on the given document model.
550     *
551     * @param docModel the document model that needs modified
552     */
553    DocumentModel saveDocument(DocumentModel docModel);
554
555    /**
556     * Bulk document saving.
557     *
558     * @param docModels the document models that needs to be saved
559     */
560    void saveDocuments(DocumentModel[] docModels);
561
562    /**
563     * Check if a document can be removed. This needs the REMOVE permission on the document and the REMOVE_CHILDREN
564     * permission on the parent.
565     * <p>
566     * For an archived version to be removeable, it must not be referenced from any proxy or be the base of a working
567     * document, and the REMOVE permission must be available on the working document (or the user must be an
568     * administrator if no working document exists).
569     *
570     * @param docRef the document
571     * @return true if the document can be removed
572     */
573    boolean canRemoveDocument(DocumentRef docRef);
574
575    /**
576     * Removes this document and all its children, if any.
577     *
578     * @param docRef the reference to the document to remove
579     */
580    void removeDocument(DocumentRef docRef);
581
582    /**
583     * Bulk method to remove documents.
584     * <p>
585     * This method is safe with respect to orderings: it doesn't fail if an ancestor of a document occurs before the
586     * document.
587     * </p>
588     *
589     * @param docRefs the refs to the document to remove
590     */
591    void removeDocuments(DocumentRef[] docRefs);
592
593    /**
594     * Removes all children from the given document.
595     *
596     * @param docRef the reference to the document to remove
597     */
598    void removeChildren(DocumentRef docRef);
599
600    /**
601     * Copies the source document to the destination folder under the given name. If the name is null the original name
602     * is preserved.
603     * <p>
604     * If the destination document is not a folder or it doesn't exists then throws an exception.
605     * <p>
606     * If the source is a proxy the destination will be a copy of the proxy.
607     *
608     * @param src the source document reference
609     * @param dst the destination folder reference
610     * @param name the new name of the file or null if the original name must be preserved
611     * @param copyOptions the options for copy
612     */
613    DocumentModel copy(DocumentRef src, DocumentRef dst, String name, CopyOption... copyOptions);
614
615    /**
616     * Copies the source document to the destination folder under the given name. If the name is null the original name
617     * is preserved.
618     * <p>
619     * If the destination document is not a folder or it doesn't exists then throws an exception.
620     * <p>
621     * If the source is a proxy the destination will be a copy of the proxy.
622     *
623     * @param src the source document reference
624     * @param dst the destination folder reference
625     * @param name the new name of the file or null if the original name must be preserved
626     * @param resetLifeCycle the property that flagged whether reset destination document lifecycle or not
627     * @since 5.7
628     * @deprecated Since 8.2. Use {@link #copy(DocumentRef, DocumentRef, String, CopyOption...)} instead
629     */
630    @Deprecated
631    DocumentModel copy(DocumentRef src, DocumentRef dst, String name, boolean resetLifeCycle);
632
633    /**
634     * Bulk copy. Destination must be a folder document.
635     *
636     * @param src the documents to copy
637     * @param dst the destination folder
638     * @param copyOptions the options for copy
639     * @since 8.2
640     */
641    List<DocumentModel> copy(List<DocumentRef> src, DocumentRef dst, CopyOption... copyOptions);
642
643    /**
644     * Bulk copy. Destination must be a folder document.
645     *
646     * @param src the documents to copy
647     * @param dst the destination folder
648     * @param resetLifeCycle the property that flagged whether reset destination document lifecycle or not
649     * @since 5.7
650     * @deprecated Since 8.2. Use {@link #copy(List, DocumentRef, CopyOption...)} instead
651     */
652    @Deprecated
653    List<DocumentModel> copy(List<DocumentRef> src, DocumentRef dst, boolean resetLifeCycle);
654
655    /**
656     * Work like copy but in the case of a source proxy the destination will be a new document instead of a proxy.
657     *
658     * @see CoreSession#copy(DocumentRef, DocumentRef, String, CopyOption...)
659     * @param src the source document reference
660     * @param dst the destination folder reference
661     * @param name the new name of the file or null if the original name must be preserved
662     * @param copyOptions the options for copy
663     * @since 8.2
664     */
665    DocumentModel copyProxyAsDocument(DocumentRef src, DocumentRef dst, String name, CopyOption... copyOptions);
666
667    /**
668     * Work like copy but in the case of a source proxy the destination will be a new document instead of a proxy.
669     *
670     * @param src the source document reference
671     * @param dst the destination folder reference
672     * @param name the new name of the file or null if the original name must be preserved
673     * @param resetLifeCycle the property that flagged whether reset destination document lifecycle or not
674     * @since 5.7
675     * @deprecated Since 8.2. Use {@link #copyProxyAsDocument(DocumentRef, DocumentRef, String, CopyOption...)} instead
676     */
677    @Deprecated
678    DocumentModel copyProxyAsDocument(DocumentRef src, DocumentRef dst, String name, boolean resetLifeCycle);
679
680    /**
681     * Bulk copyProxyAsDocument. Destination must be a folder document.
682     *
683     * @param src the documents to copy
684     * @param dst the destination folder
685     * @param copyOptions the options of copy
686     * @since 8.2
687     */
688    List<DocumentModel> copyProxyAsDocument(List<DocumentRef> src, DocumentRef dst, CopyOption... copyOptions);
689
690    /**
691     * Bulk copyProxyAsDocument. Destination must be a folder document.
692     *
693     * @param src the documents to copy
694     * @param dst the destination folder
695     * @param resetLifeCycle the property that flagged whether reset destination document lifecycle or not
696     * @since 5.7
697     * @deprecated Since 8.2. Use {@link #copyProxyAsDocument(List, DocumentRef, CopyOption...)} instead
698     */
699    @Deprecated
700    List<DocumentModel> copyProxyAsDocument(List<DocumentRef> src, DocumentRef dst, boolean resetLifeCycle);
701
702    /**
703     * Moves the source document to the destination folder under the given name. If the name is {@code null} or if there
704     * is a collision, a suitable new name is found.
705     *
706     * @param src the source document reference
707     * @param dst the destination folder reference
708     * @param name the new name of the file, or {@code null}
709     */
710    DocumentModel move(DocumentRef src, DocumentRef dst, String name);
711
712    /**
713     * Bulk move. Destination must be a folder document.
714     *
715     * @param src the documents to move
716     * @param dst the destination folder
717     */
718    void move(List<DocumentRef> src, DocumentRef dst);
719
720    /**
721     * Gets the document access control policy.
722     * <p>
723     * The returned ACP is the ACP defined on that document if any + the inherited ACL if any. If neither a local ACP
724     * nor inherited ACL exists null is returned.
725     * <p>
726     * Note that modifying the returned ACP will not affect in any way the stored document ACP. To modify the ACP you
727     * must explicitely set it by calling {@link CoreSession#setACP(DocumentRef, ACP, boolean)}
728     * <p>
729     * This method will always fetch a fresh ACP from the storage. The recommended way to get the ACP is to use
730     * {@link DocumentModel#getACP()} this way the ACP will be cached at the document model level and so you can use it
731     * for multiple permission checks without fetching it each time.
732     *
733     * @param docRef the doc ref to retrieve ACP or null if none
734     * @return the ACP
735     */
736    ACP getACP(DocumentRef docRef);
737
738    /**
739     * Sets the ACP for this document.
740     * <p>
741     * If the ACP contains an <code>INHERITED</code> ACL it will be discarded. Only ACLs relative to the current
742     * document may be changed.
743     * <p>
744     * If the <code>overwrite</code> argument is false, the ACP is merged with the existing one if any. The merge is
745     * done as follow:
746     * <ul>
747     * <li>If any ACL is that already exists on the document ACp is redefined by the new ACO then it will be replaced by
748     * the new one. So if you want to remove an ACl in this mode you need to specify an empty ACL.
749     * <li>If the new ACP contains an ACl that is not defined by the old one the it will be added to the merged ACP.
750     * <li>If the <code>owners</code> are specified then they will replace the existing ones if any. Otherwise the old
751     * owners are preserved if any. As for the ACL if you want to remove existing owners you need to specify an empty
752     * owner array (and not a null one)
753     * </ul>
754     * If the <code>overwrite</code> argument is true, the old ACP will be replaced by the new one.
755     * <p>
756     * This way if you can remove the existing ACP by specifying a null ACP and <code>overwrite</code> argument set to
757     * true.
758     * <p>
759     * Setting a null ACP when <code>overwrite</code> is false will do nothing.
760     */
761    void setACP(DocumentRef docRef, ACP acp, boolean overwrite);
762
763    /**
764     * Replace the {@code oldACE} with the {@code newACE} on the given {@code aclName}.
765     * <p>
766     *
767     * @since 7.4
768     */
769    void replaceACE(DocumentRef docRef, String aclName, ACE oldACE, ACE newACE);
770
771    /**
772     * Updates the Read ACLs for some documents.
773     * <p>
774     * For INTERNAL use by the core.
775     *
776     * @param docIds the document ids
777     * @since 9.10
778     */
779    void updateReadACLs(Collection<String> docIds);
780
781    /**
782     * Returns {@code true} if negative ACLs are allowed.
783     * <p>
784     * Negative ACLs are ACLs that include an ACE with a deny (isGranted=false). This does not include the full-blocking
785     * ACE for Everyone/Everything, which is always allowed.
786     *
787     * @return {@code true} if negative ACLs are allowed
788     * @since 6.0
789     */
790    boolean isNegativeAclAllowed();
791
792    /*
793     * Support for lazy loading
794     */
795
796    /**
797     * Retrieves a data model given a document reference and a schema.
798     * <p>
799     * For INTERNAL use by the core.
800     *
801     * @since 5.4.2
802     */
803    DataModel getDataModel(DocumentRef docRef, Schema schema);
804
805    // -------- Versioning API ---------------
806
807    /**
808     * Gets the document corresponding to the last version for the given document.
809     *
810     * @param docRef the reference to the document
811     * @return the document model corresponding to the version
812     */
813    DocumentModel getLastDocumentVersion(DocumentRef docRef);
814
815    /**
816     * Gets the document reference corresponding to the last version for the given document.
817     *
818     * @param docRef the reference to the document
819     * @return the document reference corresponding to the last version
820     */
821    DocumentRef getLastDocumentVersionRef(DocumentRef docRef);
822
823    /**
824     * Gets the head (live) document for this document.
825     *
826     * @param docRef the reference to the document
827     * @return the version
828     */
829    DocumentModel getSourceDocument(DocumentRef docRef);
830
831    /**
832     * Gets the references of the versions of the document.
833     *
834     * @param docRef the reference to the document
835     * @return a list of version references
836     * @since 1.4.1
837     */
838    List<DocumentRef> getVersionsRefs(DocumentRef docRef);
839
840    /**
841     * Retrieves all the versions for a specified document.
842     *
843     * @param docRef the reference to the document
844     * @return the list of {@link DocumentModel} representing versions, empty list if none is found.
845     */
846    List<DocumentModel> getVersions(DocumentRef docRef);
847
848    /**
849     * Retrieves all the versions for a specified document.
850     *
851     * @param docRef the reference to the document
852     * @return the list of {@link VersionModel} representing versions, empty list if none is found.
853     */
854    List<VersionModel> getVersionsForDocument(DocumentRef docRef);
855
856    /**
857     * Gets a document version, given the versionable id and label.
858     * <p>
859     * The version model contains the label of the version to look for. On return, it is filled with the version's
860     * description and creation date.
861     *
862     * @param versionableId the versionable id
863     * @param versionModel the version model holding the label
864     * @return the version, or {@code null} if not found
865     */
866    DocumentModel getVersion(String versionableId, VersionModel versionModel);
867
868    /**
869     * Gets the version label for a document, according to the versioning service.
870     *
871     * @param docModel the document
872     * @return the version label
873     */
874    String getVersionLabel(DocumentModel docModel);
875
876    /**
877     * Returns a document that represents the specified version of the document.
878     *
879     * @param docRef the reference to the document
880     * @param version the version for which we want the corresponding document
881     */
882    DocumentModel getDocumentWithVersion(DocumentRef docRef, VersionModel version);
883
884    /**
885     * Restores the given document to the specified version.
886     *
887     * @param docRef the reference to the document
888     * @param versionRef the reference to the version
889     * @param skipSnapshotCreation {@code true} if the document should not be snapshotted before being restored
890     * @param skipCheckout {@code true} if the restored document should be kept in a checked-in state
891     * @since 5.4
892     */
893    DocumentModel restoreToVersion(DocumentRef docRef, DocumentRef versionRef, boolean skipSnapshotCreation,
894            boolean skipCheckout);
895
896    /**
897     * Restores the given document to the specified version.
898     *
899     * @param docRef the reference to the document
900     * @param versionRef the reference to the version
901     * @since 5.4
902     */
903    DocumentModel restoreToVersion(DocumentRef docRef, DocumentRef versionRef);
904
905    /**
906     * Gets the version to which a checked in document is linked.
907     * <p>
908     * Returns {@code null} for a checked out document or a version or a proxy.
909     *
910     * @return the version, or {@code null}
911     */
912    DocumentRef getBaseVersion(DocumentRef docRef);
913
914    /**
915     * Checks out a versioned document.
916     *
917     * @param docRef the reference to the document
918     */
919    void checkOut(DocumentRef docRef);
920
921    /**
922     * Checks in a modified document, creating a new version.
923     *
924     * @param docRef the reference to the document
925     * @param option whether to do create a new {@link VersioningOption#MINOR} or {@link VersioningOption#MAJOR} version
926     *            during check in
927     * @param checkinComment the checkin comment
928     * @return the version just created
929     * @since 5.4
930     */
931    DocumentRef checkIn(DocumentRef docRef, VersioningOption option, String checkinComment);
932
933    /**
934     * Returns whether the current document is checked-out or not.
935     *
936     * @param docRef the reference to the document
937     */
938    boolean isCheckedOut(DocumentRef docRef);
939
940    /**
941     * Gets the version series id for a document.
942     * <p>
943     * All documents and versions derived by a check in or checkout from the same original document share the same
944     * version series id.
945     *
946     * @param docRef the document reference
947     * @return the version series id
948     * @since 5.4
949     */
950    String getVersionSeriesId(DocumentRef docRef);
951
952    /**
953     * Gets the working copy (live document) for a proxy or a version.
954     *
955     * @param docRef the document reference
956     * @return the working copy, or {@code null} if not found
957     * @since 5.4
958     */
959    DocumentModel getWorkingCopy(DocumentRef docRef);
960
961    /**
962     * Creates a generic proxy to the given document inside the given folder.
963     * <p>
964     * The document may be a version, or a working copy (live document) in which case the proxy will be a "shortcut".
965     *
966     * @since 1.6.1 (5.3.1)
967     */
968    DocumentModel createProxy(DocumentRef docRef, DocumentRef folderRef);
969
970    /** -------------------------- Query API --------------------------- * */
971
972    /**
973     * Executes the given NXQL query an returns the result.
974     *
975     * @param query the query to execute
976     * @return the query result
977     */
978    DocumentModelList query(String query);
979
980    /**
981     * Executes the given NXQL query an returns the result.
982     *
983     * @param query the query to execute
984     * @param max number of document to retrieve
985     * @return the query result
986     */
987    DocumentModelList query(String query, int max);
988
989    /**
990     * Executes the given NXQL query and returns the result that matches the filter.
991     *
992     * @param query the query to execute
993     * @param filter the filter to apply to result
994     * @return the query result
995     */
996    DocumentModelList query(String query, Filter filter);
997
998    /**
999     * Executes the given NXQL query and returns the result that matches the filter.
1000     *
1001     * @param query the query to execute
1002     * @param filter the filter to apply to result
1003     * @param max number of document to retrieve
1004     * @return the query result
1005     */
1006    DocumentModelList query(String query, Filter filter, int max);
1007
1008    /**
1009     * Executes the given NXQL query and returns the result that matches the filter.
1010     *
1011     * @param query the query to execute
1012     * @param filter the filter to apply to result
1013     * @param limit the maximum number of documents to retrieve, or 0 for all of them
1014     * @param offset the offset (starting at 0) into the list of documents
1015     * @param countTotal if {@code true}, return a {@link DocumentModelList} that includes a total size of the
1016     *            underlying list (size if there was no limit or offset)
1017     * @return the query result
1018     */
1019    DocumentModelList query(String query, Filter filter, long limit, long offset, boolean countTotal);
1020
1021    /**
1022     * Executes the given NXQL query and returns the result that matches the filter.
1023     *
1024     * @param query the query to execute
1025     * @param filter the filter to apply to result
1026     * @param limit the maximum number of documents to retrieve, or 0 for all of them
1027     * @param offset the offset (starting at 0) into the list of documents
1028     * @param countUpTo if {@code -1}, count the total size without offset/limit.<br>
1029     *            If {@code 0}, don't count the total size.<br>
1030     *            If {@code n}, count the total number if there are less than n documents otherwise set the size to
1031     *            {@code -1}.
1032     * @return the query result
1033     * @since 5.6
1034     */
1035    DocumentModelList query(String query, Filter filter, long limit, long offset, long countUpTo);
1036
1037    /**
1038     * Executes the given query and returns the result that matches the filter.
1039     *
1040     * @param query the query to execute
1041     * @param queryType the query type, like "NXQL"
1042     * @param filter the filter to apply to result
1043     * @param limit the maximum number of documents to retrieve, or 0 for all of them
1044     * @param offset the offset (starting at 0) into the list of documents
1045     * @param countTotal if {@code true}, return a {@link DocumentModelList} that includes a total size of the
1046     *            underlying list (size if there was no limit or offset)
1047     * @return the query result
1048     * @since 5.5
1049     */
1050    DocumentModelList query(String query, String queryType, Filter filter, long limit, long offset, boolean countTotal);
1051
1052    /**
1053     * Executes the given query and returns the result that matches the filter.
1054     *
1055     * @param query the query to execute
1056     * @param queryType the query type, like "NXQL"
1057     * @param filter the filter to apply to result
1058     * @param limit the maximum number of documents to retrieve, or 0 for all of them
1059     * @param offset the offset (starting at 0) into the list of documents
1060     * @param countUpTo if {@code -1}, return a {@link DocumentModelList} that includes a total size of the underlying
1061     *            list (size if there was no limit or offset). <br>
1062     *            If {@code 0}, don't return the total size of the underlying list. <br>
1063     *            If {@code n}, return the total size of the underlying list when the size is smaller than {@code n}
1064     *            else return a total size of {@code -1}.
1065     * @return the query result
1066     * @since 5.6
1067     */
1068    DocumentModelList query(String query, String queryType, Filter filter, long limit, long offset, long countUpTo);
1069
1070    /**
1071     * Executes the given query and returns an iterable of maps containing the requested properties (which must be
1072     * closed when done).
1073     *
1074     * @param query the query to execute
1075     * @param queryType the query type, usually "NXQL"
1076     * @param params optional query-type-dependent parameters
1077     * @return an {@link IterableQueryResult}, which <b>must</b> be closed after use
1078     */
1079    IterableQueryResult queryAndFetch(String query, String queryType, Object... params);
1080
1081    /**
1082     * Executes the given query and returns an iterable of maps containing the requested properties (which must be
1083     * closed when done).
1084     * <p>
1085     * It's possible to specify {@code distinctDocuments = true} to get a maximum of one row of results per document,
1086     * this will behave differently only when the {@code WHERE} clause contains wildcards.
1087     *
1088     * @param query the query to execute
1089     * @param queryType the query type, usually "NXQL"
1090     * @param distinctDocuments if {@code true} then a maximum of one row per document will be returned
1091     * @param params optional query-type-dependent parameters
1092     * @return an {@link IterableQueryResult}, which <b>must</b> be closed after use
1093     * @since 7.10-HF04, 8.2
1094     */
1095    IterableQueryResult queryAndFetch(String query, String queryType, boolean distinctDocuments, Object... params);
1096
1097    /**
1098     * Executes the given NXQL query and returns the result that matches the filter.
1099     *
1100     * @param query the query to execute
1101     * @param limit the maximum number of documents to retrieve, or 0 for all of them
1102     * @param offset the offset (starting at 0) into the list of documents
1103     * @return the query result
1104     * @since 7.10-HF25, 8.10-HF06, 9.2
1105     */
1106    PartialList<Map<String, Serializable>> queryProjection(String query, long limit, long offset);
1107
1108    /**
1109     * Executes the given NXQL query and returns the result that matches the filter.
1110     *
1111     * @param query the query to execute
1112     * @param limit the maximum number of documents to retrieve, or 0 for all of them
1113     * @param offset the offset (starting at 0) into the list of documents
1114     * @param countTotal if {@code true}, return a {@link PartialList} that includes a total size of the underlying list
1115     *            (size if there was no limit or offset)
1116     * @return the query result
1117     * @since 7.10-HF25, 8.10-HF06, 9.2
1118     */
1119    PartialList<Map<String, Serializable>> queryProjection(String query, long limit, long offset, boolean countTotal);
1120
1121    /**
1122     * Executes the given NXQL query and returns the result that matches the filter.
1123     *
1124     * @param query the query to execute
1125     * @param queryType the query type, like "NXQL"
1126     * @param distinctDocuments if {@code true} then a maximum of one row per document will be returned
1127     * @param limit the maximum number of documents to retrieve, or 0 for all of them
1128     * @param offset the offset (starting at 0) into the list of documents
1129     * @param countUpTo if {@code -1}, return a {@link PartialList} that includes a total size of the underlying list
1130     *            (size if there was no limit or offset). <br>
1131     *            If {@code 0}, don't return the total size of the underlying list. <br>
1132     *            If {@code n}, return the total size of the underlying list when the size is smaller than {@code n}
1133     *            else return a total size of {@code -1}.
1134     * @param params optional query-type-dependent parameters
1135     * @return the query result
1136     * @since 7.10-HF25, 8.10-HF06, 9.2
1137     */
1138    PartialList<Map<String, Serializable>> queryProjection(String query, String queryType, boolean distinctDocuments,
1139            long limit, long offset, long countUpTo, Object... params);
1140
1141    /**
1142     * Executes the given query and returns the first batch of results containing id of documents, next batch must be
1143     * requested within the {@code keepAliveSeconds} delay.
1144     *
1145     * @param query The NXQL query to execute
1146     * @param batchSize The expected result batch size, note that more results can be returned when the backend don't
1147     *            implement properly this feature
1148     * @param keepAliveSeconds The scroll context lifetime in seconds
1149     * @return A {@link ScrollResult} including the search results and a scroll id, to be passed to the subsequent calls
1150     *         to {@link #scroll(String)}
1151     * @since 8.4
1152     */
1153    ScrollResult<String> scroll(String query, int batchSize, int keepAliveSeconds);
1154
1155    /**
1156     * Get the next batch of results containing id of documents, the {@code scrollId} is part of the previous
1157     * {@link ScrollResult} response.
1158     *
1159     * @throws NuxeoException when the {@code scrollId} is unknown or when the scroll operation has timed out
1160     * @since 8.4
1161     */
1162    ScrollResult<String> scroll(String scrollId);
1163
1164    /** -------------------------- Security API --------------------------- * */
1165
1166    /**
1167     * Retrieves the available security permissions existing in the system.
1168     * <p>
1169     *
1170     * @return a raw list of permission names, either basic or group names
1171     */
1172    // TODO: (Hardcoded at the moment. In the future wil get data from
1173    // LDAP/database.)
1174    List<String> getAvailableSecurityPermissions();
1175
1176    /**
1177     * Turns the document into a record.
1178     * <p>
1179     * A record is a document with specific capabilities related to mandatory retention until a given date, and legal
1180     * holds. In addition, its main blob receives special treatment from the document blob manager to make sure it's
1181     * never shared with another blob at the storage level, and is deleted as soon as the record is deleted.
1182     * <p>
1183     * If the document is already a record, this method has no effect.
1184     * <p>
1185     * The permission {@value org.nuxeo.ecm.core.api.security.SecurityConstants#MAKE_RECORD} is required.
1186     *
1187     * @param docRef the document
1188     * @see #isRecord
1189     * @since 11.1
1190     */
1191    void makeRecord(DocumentRef docRef);
1192
1193    /**
1194     * Checks if the document is a record.
1195     *
1196     * @param docRef the document
1197     * @return {@code true} if the document is a record, {@code false} otherwise
1198     * @see #makeRecord
1199     * @since 11.1
1200     */
1201    boolean isRecord(DocumentRef docRef);
1202
1203    /**
1204     * The special date that corresponds to a retention date in the indeterminate future.
1205     *
1206     * @see #setRetainUntil
1207     * @see #RETAIN_UNTIL_INDETERMINATE
1208     * @since 11.1
1209     */
1210    String RETAIN_UNTIL_INDETERMINATE_ISO = "9999-01-01T00:00Z";
1211
1212    /**
1213     * The special date that corresponds to a retention date in the indeterminate future.
1214     *
1215     * @see #setRetainUntil
1216     * @see #RETAIN_UNTIL_INDETERMINATE_ISO
1217     * @since 11.1
1218     */
1219    Calendar RETAIN_UNTIL_INDETERMINATE = GregorianCalendar.from(ZonedDateTime.parse(RETAIN_UNTIL_INDETERMINATE_ISO));
1220
1221    /**
1222     * Sets the retention date on the document (a record).
1223     * <p>
1224     * If no previous retention date was set, or if the previous retention date was
1225     * {@linkplain #RETAIN_UNTIL_INDETERMINATE indeterminate}, or if the previous retention date was <em>before</em>
1226     * the given value, then the retention date is set to the given value.
1227     * <p>
1228     * If the previous retention date was <em>after</em> the given value (that is, if trying to reduce the retention
1229     * time), an exception is thrown.
1230     * <p>
1231     * If the given value is {@code null} and the previous retention date is in the past (it has already expired), then
1232     * the retention date is set to {@code null}.
1233     * <p>
1234     * The permission {@value org.nuxeo.ecm.core.api.security.SecurityConstants#SET_RETENTION} is required.
1235     *
1236     * @param docRef the document (a record)
1237     * @param retainUntil the new retention date
1238     * @param comment an optional comment passed to the associated events
1239     * @throws PropertyException if trying to reduce the retention time, or if the document is not a record
1240     * @see #getRetainUntil
1241     * @see #RETAIN_UNTIL_INDETERMINATE
1242     * @since 11.1
1243     */
1244    void setRetainUntil(DocumentRef docRef, Calendar retainUntil, String comment) throws PropertyException;
1245
1246    /**
1247     * Gets the retention date for the document.
1248     *
1249     * @param docRef the document
1250     * @return the retention date, or {@value org.nuxeo.ecm.core.api.security.SecurityConstants#SET_RETENTION} for a
1251     *         retention in the indeterminate future, or {@code null} if there is no retention date
1252     * @see #setRetainUntil
1253     * @see #RETAIN_UNTIL_INDETERMINATE
1254     * @since 11.1
1255     */
1256    Calendar getRetainUntil(DocumentRef docRef);
1257
1258    /**
1259     * Sets or removes the legal hold on the document (a record).
1260     * <p>
1261     * The permission {@value org.nuxeo.ecm.core.api.security.SecurityConstants#MANAGE_LEGAL_HOLD} is required.
1262     *
1263     * @param docRef the document (a record)
1264     * @param hold {@code true} to set a legal hold, {@code false} to remove it
1265     * @param comment an optional comment passed to the associated events
1266     * @see #hasLegalHold
1267     * @throws PropertyException if the document is not a record
1268     * @since 11.1
1269     */
1270    void setLegalHold(DocumentRef docRef, boolean hold, String comment);
1271
1272    /**
1273     * Checks if the document has a legal hold set.
1274     *
1275     * @param docRef the document
1276     * @return {@code true} if a legal hold has been set on the document, {@code false} otherwise
1277     * @see #setLegalHold
1278     * @since 11.1
1279     */
1280    boolean hasLegalHold(DocumentRef docRef);
1281
1282    /**
1283     * Checks if the document has a retention date in the future or has a legal hold.
1284     *
1285     * @param docRef the document
1286     * @return {@code true} if the document has a retention date in the future or if it has a legal hold, {@code false}
1287     *         otherwise
1288     * @see #getRetainUntil
1289     * @see #hasLegalHold
1290     * @since 11.1
1291     */
1292    boolean isUnderRetentionOrLegalHold(DocumentRef docRef);
1293
1294    /**
1295     * Checks whether a document is under active retention.
1296     *
1297     * @param docRef the document reference
1298     * @return {@code true} if the document is under active retention
1299     * @since 9.3
1300     * @deprecated since 11.1, unused, use {@link #hasLegalHold} instead
1301     */
1302    @Deprecated
1303    boolean isRetentionActive(DocumentRef docRef);
1304
1305    /**
1306     * Sets or unsets a document as under active retention.
1307     *
1308     * @param docRef the document reference
1309     * @param retentionActive whether the retention should be set or unset as active
1310     * @since 9.3
1311     * @deprecated since 11.1, unused, use {@link #setLegalHold} instead
1312     */
1313    @Deprecated
1314    void setRetentionActive(DocumentRef docRef, boolean retentionActive);
1315
1316    /**
1317     * Checks if this document is in the trash.
1318     *
1319     * @param docRef the document reference
1320     * @return true if the document is in the trash, false otherwise.
1321     * @since 10.1
1322     */
1323    boolean isTrashed(DocumentRef docRef);
1324
1325    /**
1326     * Returns the life cycle of the document.
1327     *
1328     * @param docRef the document reference
1329     * @return the life cycle as a string
1330     * @implNote See org.nuxeo.ecm.core.lifecycle package
1331     */
1332    String getCurrentLifeCycleState(DocumentRef docRef);
1333
1334    /**
1335     * Returns the life cycle policy of the document.
1336     *
1337     * @param docRef the document reference
1338     * @return the life cycle policy
1339     * @implNote See org.nuxeo.ecm.core.lifecycle package
1340     */
1341    String getLifeCyclePolicy(DocumentRef docRef);
1342
1343    /**
1344     * Follows a given life cycle transition.
1345     * <p>
1346     * This will update the current life cycle of the document.
1347     *
1348     * @param docRef the document reference
1349     * @param transition the name of the transition to follow
1350     * @return a boolean representing the status if the operation
1351     * @throws LifeCycleException if the transition cannot be followed
1352     */
1353    boolean followTransition(DocumentRef docRef, String transition) throws LifeCycleException;
1354
1355    /**
1356     * Follows a given life cycle transition.
1357     * <p>
1358     * This will update the current life cycle of the document.
1359     *
1360     * @param doc the document model
1361     * @param transition the name of the transition to follow
1362     * @return a boolean representing the status if the operation
1363     * @throws LifeCycleException if the transition cannot be followed
1364     */
1365    boolean followTransition(DocumentModel doc, String transition) throws LifeCycleException;
1366
1367    /**
1368     * Gets the allowed state transitions for this document.
1369     *
1370     * @param docRef the document reference
1371     * @return a collection of state transitions as string
1372     */
1373    Collection<String> getAllowedStateTransitions(DocumentRef docRef);
1374
1375    /**
1376     * Reinitializes the life cycle state of the document to its default state.
1377     *
1378     * @param docRef the document
1379     * @since 5.4.2
1380     */
1381    void reinitLifeCycleState(DocumentRef docRef);
1382
1383    /**
1384     * Retrieves the given field value from the given schema for all the given documents.
1385     *
1386     * @param docRefs the document references
1387     * @param schema the schema
1388     * @param field the field name
1389     * @return the field values in the same order as the given docRefs
1390     */
1391    Object[] getDataModelsField(DocumentRef[] docRefs, String schema, String field);
1392
1393    /**
1394     * Creates an array with all parent refs starting from the given document up to the root. So the return value will
1395     * have [0] = parent ref; [1] = parent parent ref... etc.
1396     *
1397     * @return an array with ancestor documents ref
1398     */
1399    DocumentRef[] getParentDocumentRefs(DocumentRef docRef);
1400
1401    /**
1402     * Retrieves the given field value from the given schema for the given document along with all its parent documents.
1403     *
1404     * @param docRef the document reference
1405     * @param schema the schema
1406     * @param field the field name
1407     * @return an array with field values of all documents on the path from the given document to the root
1408     */
1409    Object[] getDataModelsFieldUp(DocumentRef docRef, String schema, String field);
1410
1411    /**
1412     * Sets a lock on the given document.
1413     *
1414     * @param docRef the document reference
1415     * @return the lock info that was set
1416     * @throws LockException if the document is already locked by another user
1417     * @since 5.4.2
1418     */
1419    Lock setLock(DocumentRef docRef) throws LockException;
1420
1421    /**
1422     * Gets the lock info on the given document.
1423     * <p>
1424     * Lock info is never cached, and needs to use a separate transaction in a separate thread, so care should be taken
1425     * to not call this method needlessly.
1426     *
1427     * @param docRef the document reference
1428     * @return the lock info if the document is locked, or {@code null} otherwise
1429     * @since 5.4.2
1430     */
1431    Lock getLockInfo(DocumentRef docRef);
1432
1433    /**
1434     * Removes the lock on the given document.
1435     * <p>
1436     * The caller principal should be the same as the one who set the lock or to belongs to the administrator group,
1437     * otherwise an exception will be throw.
1438     * <p>
1439     * If the document was not locked, does nothing.
1440     * <p>
1441     * Returns the previous lock info.
1442     *
1443     * @param docRef the document to unlock
1444     * @return the removed lock info, or {@code null} if there was no lock
1445     * @since 5.4.2
1446     * @throws LockException if the document is locked by someone else
1447     */
1448    Lock removeLock(DocumentRef docRef) throws LockException;
1449
1450    /**
1451     * Applies default Read permissions on root JCR Document for the given user or group name. It can only be called by
1452     * Administrators.
1453     * <p>
1454     * Usage: As an administrator, you may want to add new users or groups. This method needs to be called to grand
1455     * default reading permissions on the root document of the repository for the newly created users/groups.
1456     */
1457    void applyDefaultPermissions(String userOrGroupName);
1458
1459    /**
1460     * Publishes the document in a section overwriting any existing proxy to the same document. This is simmilar to
1461     * publishDocument(docToPublish, section, true);
1462     *
1463     * @return The proxy document that was created
1464     * @since 1.4.1 for the case where docToPublish is a proxy
1465     */
1466    DocumentModel publishDocument(DocumentModel docToPublish, DocumentModel section);
1467
1468    /**
1469     * Publishes the document in a section.
1470     *
1471     * @return The proxy document that was created
1472     */
1473    DocumentModel publishDocument(DocumentModel docToPublish, DocumentModel section, boolean overwriteExistingProxy);
1474
1475    /**
1476     * Finds the proxies for a document. If the parent is not null, the search will be limited to its direct children.
1477     * <p>
1478     * If the document is a version, then only proxies to that version will be looked up.
1479     * <p>
1480     * If the document is a proxy, then all similar proxies (pointing to any version of the same versionable) are
1481     * retrieved.
1482     *
1483     * @param docRef the target document for the proxies
1484     * @param folderRef the folder where proxies are located or {@code null}
1485     * @return the list of the proxies. An empty list is returned if no proxy are found
1486     * @since 1.4.1 for the case where docRef is a proxy
1487     */
1488    DocumentModelList getProxies(DocumentRef docRef, DocumentRef folderRef);
1489
1490    /**
1491     * Returns the type of his parent SuperSpace (workspace, section, etc.). SuperSpace is qualified by the SuperSpace
1492     * facet.
1493     */
1494    String getSuperParentType(DocumentModel doc);
1495
1496    /**
1497     * Returns the parent SuperSpace (workspace, section, etc.). SuperSpace is qualified by the SuperSpace facet.
1498     *
1499     * @return DocumentModel of SuperSpace
1500     */
1501    DocumentModel getSuperSpace(DocumentModel doc);
1502
1503    /**
1504     * Returns the repository name against which this core session is bound.
1505     *
1506     * @return the repository name used currently used as an identifier
1507     */
1508    String getRepositoryName();
1509
1510    /**
1511     * Gets system property of the specified type for the document ref.
1512     */
1513    <T extends Serializable> T getDocumentSystemProp(DocumentRef ref, String systemProperty, Class<T> type);
1514
1515    /**
1516     * Sets given value as a system property.
1517     */
1518    <T extends Serializable> void setDocumentSystemProp(DocumentRef ref, String systemProperty, T value);
1519
1520    /**
1521     * Given a parent document, order the source child before the destination child. The source and destination must be
1522     * name of child documents of the given parent document. (a document name can be retrieved using
1523     * <code>docModel.getName()</code>) To place the source document at the end of the children list use a null
1524     * destination node.
1525     *
1526     * @param parent the parent document
1527     * @param src the document to be moved (ordered)
1528     * @param dest the document before which the reordered document will be placed If null the source document will be
1529     *            placed at the end of the children list
1530     */
1531    void orderBefore(DocumentRef parent, String src, String dest);
1532
1533    /**
1534     * Internal method - it is used internally by {@link DocumentModel#refresh()}
1535     * <p>
1536     * Get fresh data from a document given a description of what kind of data should be refetched.
1537     * <p>
1538     * The refresh information is specified using a bit mask. See {@link DocumentModel} for all accepted flags.
1539     * <p>
1540     * When the flag {@link DocumentModel#REFRESH_CONTENT_IF_LOADED} is specified a third argument must be passed
1541     * representing the schema names for document parts to refresh. This argument is ignored if the flag is not
1542     * specified or no schema names are provided
1543     *
1544     * @param ref the document reference
1545     * @param refreshFlags refresh flags as defined in {@link DocumentModel}
1546     * @param schemas the schema names if a partial content refresh is required
1547     * @return a DocumentModelRefresh object
1548     */
1549    DocumentModelRefresh refreshDocument(DocumentRef ref, int refreshFlags, String[] schemas);
1550
1551    /**
1552     * Provides the full list of all permissions or groups of permissions that contain the given one (inclusive). It
1553     * makes the method {@code org.nuxeo.ecm.core.security.SecurityService#getPermissionsToCheck(String)} available
1554     * remotely.
1555     *
1556     * @return the list, as an array of strings.
1557     */
1558    String[] getPermissionsToCheck(String permission);
1559
1560    /**
1561     * Find the first parent with the given {@code facet} and adapt it on the {@code adapterClass}.
1562     * <p>
1563     * This method does not check the permissions on the document to be adapted of this {@code CoreSession}'s
1564     * {@code Principal}, and so the adapter must not need other schemas from the {@code DocumentModel} except the
1565     * schemas related to the given facet.
1566     *
1567     * @return the first parent with the given {@code facet} adapted, or {@code null} if no parent found or the document
1568     *         does not support the given {@code adapterClass}.
1569     * @since 5.4.2
1570     */
1571    <T extends DetachedAdapter> T adaptFirstMatchingDocumentWithFacet(DocumentRef docRef, String facet,
1572            Class<T> adapterClass);
1573
1574    /**
1575     * Gets the fulltext extracted from the binary fields. We defined a new API for that to avoid to store in the cache
1576     * the fulltext properties which could be huge. This method handle if document is a proxy or not. Historically, VCS
1577     * doesn't store fulltext properties for proxies (note that DBS does).
1578     *
1579     * @param ref the document reference
1580     * @return the fulltext map or {@code null} if not supported.
1581     * @since 5.9.3
1582     */
1583    Map<String, String> getBinaryFulltext(DocumentRef ref);
1584
1585    /**
1586     * The key in the map returned by {@link #getBinaryFulltext} that corresponds to the main binary fulltext
1587     * extraction.
1588     *
1589     * @since 11.1
1590     */
1591    String BINARY_FULLTEXT_MAIN_KEY = "binarytext";
1592
1593    /** @since 8.2 */
1594    enum CopyOption {
1595
1596        RESET_LIFE_CYCLE,
1597
1598        RESET_CREATOR;
1599
1600        public static boolean isResetLifeCycle(CopyOption... options) {
1601            return Arrays.asList(options).contains(RESET_LIFE_CYCLE);
1602        }
1603
1604        public static boolean isResetCreator(CopyOption... options) {
1605            return Arrays.asList(options).contains(RESET_CREATOR);
1606        }
1607
1608    }
1609
1610    /**
1611     * Gets the current change token for the document.
1612     * <p>
1613     * The change token is an opaque string which is modified every time the document is changed.
1614     * <p>
1615     * Before saving a document through {@link CoreSession#saveDocument} it's possible to pass an expected change token
1616     * in the document context data through {@code doc.putContextData(CoreSession.CHANGE_TOKEN, expectedChangeToken)}.
1617     * If the change token does not match the stored one, it means that a concurrent update happened, and a
1618     * {@link org.nuxeo.ecm.core.api.ConcurrentUpdateException ConcurrentUpdateException} will be thrown.
1619     *
1620     * @param ref the document reference
1621     * @return the change token
1622     * @since 9.1
1623     * @see DocumentModel#putContextData
1624     * @see #CHANGE_TOKEN
1625     * @see #getChangeToken
1626     */
1627    String getChangeToken(DocumentRef ref);
1628
1629    /**
1630     * Gets a document if it exists, otherwise creates it. This is done atomically to prevent different threads from
1631     * trying to create the same document. If the document did not exist and is therefore created, the current
1632     * transaction is committed and the newly-created document is also committed in its own transaction.
1633     * <p>
1634     * WARNING: As the current transaction is impacted, using this method instead of
1635     * {@link #createDocument(DocumentModel)} could lead to inconsistent behaviour in case of rollback.
1636     *
1637     * @param docModel the document model
1638     * @return the existing or created document
1639     * @since 9.3
1640     */
1641    DocumentModel getOrCreateDocument(DocumentModel docModel);
1642
1643    /**
1644     * Gets a document if it exists, otherwise creates it. This is done atomically to prevent different threads from
1645     * trying to create the same document. If the document did not exist and is therefore created, the current
1646     * transaction is committed and the newly-created document is also committed in its own transaction.
1647     * <p>
1648     * WARNING: As the current transaction is impacted, using this method instead of
1649     * {@link #createDocument(DocumentModel)} could lead to inconsistent behaviour in case of rollback.
1650     *
1651     * @param docModel the document model
1652     * @param postCreate the function to apply after creating the document
1653     * @return the existing or created document
1654     * @since 9.3
1655     */
1656    DocumentModel getOrCreateDocument(DocumentModel docModel, Function<DocumentModel, DocumentModel> postCreate);
1657
1658}