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