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