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