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