001/*
002 * (C) Copyright 2006-2019 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.Calendar;
024import java.util.Collection;
025import java.util.Map;
026import java.util.Set;
027
028import org.nuxeo.common.utils.Path;
029import org.nuxeo.ecm.core.api.model.DocumentPart;
030import org.nuxeo.ecm.core.api.model.Property;
031import org.nuxeo.ecm.core.api.model.PropertyVisitor;
032import org.nuxeo.ecm.core.api.model.resolver.PropertyObjectResolver;
033import org.nuxeo.ecm.core.api.security.ACP;
034import org.nuxeo.ecm.core.schema.DocumentType;
035
036/**
037 * The document model is a serializable representation of a core document.
038 * <p>
039 * The document model is made from several data models, each data model is bound to a schema. All the information about
040 * a document (like security) is expressed using schemas (and implicitly data models).
041 * <p>
042 * Data models are lazily loaded as they are needed. At document model creation only data models corresponding to the
043 * default schemas are loaded. The default schemas are configured in the type manager through extension points.
044 *
045 * @see CoreSession
046 */
047public interface DocumentModel extends Serializable {
048
049    int REFRESH_STATE = 1; // "small" state (life cycle, lock, versioning)
050
051    /** @deprecated since 10.1, has no effect. */
052    @Deprecated
053    int REFRESH_PREFETCH = 4;
054
055    int REFRESH_ACP_IF_LOADED = 8; // refresh now only if already loaded
056
057    int REFRESH_ACP_LAZY = 16; // refresh later in lazy mode
058
059    int REFRESH_ACP = 32; // refresh now
060
061    int REFRESH_CONTENT_IF_LOADED = 64; // refresh now only if already loaded
062
063    int REFRESH_CONTENT_LAZY = 128; // refresh later in lazy mode
064
065    int REFRESH_CONTENT = 256; // refresh now
066
067    int REFRESH_IF_LOADED = REFRESH_STATE | REFRESH_ACP_IF_LOADED | REFRESH_CONTENT_IF_LOADED;
068
069    int REFRESH_LAZY = REFRESH_STATE | REFRESH_ACP_LAZY | REFRESH_CONTENT_LAZY;
070
071    int REFRESH_ALL = REFRESH_STATE | REFRESH_ACP | REFRESH_CONTENT;
072
073    int REFRESH_DEFAULT = REFRESH_STATE | REFRESH_ACP_IF_LOADED | REFRESH_CONTENT_LAZY;
074
075    /**
076     * Gets the document type object.
077     *
078     * @return the document type object
079     */
080    DocumentType getDocumentType();
081
082    /**
083     * Returns the repository name and principal when the document is attached.
084     *
085     * @deprecated since 11.1
086     */
087    @Deprecated
088    String getSessionId();
089
090    /**
091     * Gets the principal attached to this document's session.
092     *
093     * @return the principal
094     * @since 11.1
095     */
096    NuxeoPrincipal getPrincipal();
097
098    /**
099     * Gets the core session to which this document is tied.
100     * <p>
101     * This may be null if the document has been detached from a session.
102     *
103     * @return the core session
104     * @since 5.2.GA
105     */
106    CoreSession getCoreSession();
107
108    /**
109     * Detaches the documentImpl from its existing session, so that it can survive beyond the session's closing.
110     *
111     * @param loadAll if {@code true}, load all data and ACP from the session before detaching
112     * @since 5.6
113     */
114    void detach(boolean loadAll);
115
116    /**
117     * Reattaches a document to an existing session.
118     *
119     * @param coreSession the session to attach to
120     * @since 11.1
121     */
122    void attach(CoreSession coreSession);
123
124    /**
125     * Checks whether this document is attached to a session.
126     *
127     * @return {@code true} if the document is attached to a session
128     * @since 11.1
129     */
130    boolean isAttached();
131
132    /**
133     * Gets a reference to the core document that can be used either remotely or locally (opens the core JVM).
134     *
135     * @return the document reference
136     */
137    DocumentRef getRef();
138
139    /**
140     * Retrieves the parent reference of the current document.
141     *
142     * @return the parent reference or null if no parent
143     */
144    DocumentRef getParentRef();
145
146    /**
147     * Gets the document UUID.
148     *
149     * @return the document UUID
150     */
151    String getId();
152
153    /**
154     * Gets the document name.
155     *
156     * @return the document name
157     */
158    String getName();
159
160    /**
161     * Gets the document's position in its containing folder (if ordered).
162     *
163     * @return the position, or {@code null} if the containing folder is not ordered
164     * @since 6.0
165     */
166    Long getPos();
167
168    /**
169     * Get a text suitable to be shown in a UI for this document.
170     *
171     * @return the title or the internal name if no title could be found
172     */
173    String getTitle();
174
175    /**
176     * Gets the document path as a string.
177     *
178     * @return the document path as string
179     */
180    String getPathAsString();
181
182    /**
183     * Gets the document path.
184     *
185     * @return the document path as string
186     */
187    Path getPath();
188
189    /**
190     * Gets the document type name.
191     *
192     * @return the document type name
193     */
194    String getType();
195
196    /**
197     * Gets the schemas available on this document (from the type and the facets).
198     *
199     * @return the schemas
200     * @since 5.4.2
201     */
202    String[] getSchemas();
203
204    /**
205     * Checks if the document has the given schema, either from its type or added on the instance through a facet.
206     *
207     * @param schema the schema name
208     * @return {@code true} if the document has the schema
209     */
210    boolean hasSchema(String schema);
211
212    /**
213     * Gets the facets available on this document (from the type and the instance facets).
214     *
215     * @return the facets
216     * @since 5.4.2
217     */
218    Set<String> getFacets();
219
220    /**
221     * Checks if the document has a facet, either from its type or added on the instance.
222     *
223     * @param facet the facet name
224     * @return {@code true} if the document has the facet
225     */
226    boolean hasFacet(String facet);
227
228    /**
229     * Adds a facet to the document instance.
230     * <p>
231     * Does nothing if the facet was already present on the document.
232     *
233     * @param facet the facet name
234     * @return {@code true} if the facet was added, or {@code false} if it is already present
235     * @throws IllegalArgumentException if the facet does not exist
236     * @since 5.4.2
237     */
238    boolean addFacet(String facet);
239
240    /**
241     * Removes a facet from the document instance.
242     * <p>
243     * It's not possible to remove a facet coming from the document type.
244     *
245     * @param facet the facet name
246     * @return {@code true} if the facet was removed, or {@code false} if it isn't present or is present on the type or
247     *         does not exit
248     * @since 5.4.2
249     */
250    boolean removeFacet(String facet);
251
252    /**
253     * INTERNAL, not for public use.
254     * <p>
255     * Gets a list with the currently fetched data models.
256     *
257     * @return the data models that are already fetched as a collection
258     * @deprecated since 8.4, internal method
259     * @see #getSchemas
260     * @see #getProperties
261     * @see #getPropertyObject
262     * @see #getPropertyObjects
263     */
264    @Deprecated
265    Collection<DataModel> getDataModelsCollection();
266
267    /**
268     * Gets the data models.
269     *
270     * @return the data models that are already fetched.
271     * @deprecated since 8.4, use direct {@link Property} getters instead
272     * @see #getSchemas
273     * @see #getProperties
274     * @see #getPropertyObject
275     * @see #getPropertyObjects
276     */
277    @Deprecated
278    Map<String, DataModel> getDataModels();
279
280    /**
281     * Gets the data model corresponding to the given schema.
282     * <p>
283     * Null is returned if the document type has no such schema.
284     *
285     * @param schema the schema name
286     * @return the data model or null if no such schema is supported
287     * @deprecated since 8.4, use direct {@link Property} getters instead
288     * @see #getSchemas
289     * @see #getProperties
290     * @see #getPropertyObject
291     * @see #getPropertyObjects
292     */
293    @Deprecated
294    DataModel getDataModel(String schema);
295
296    /**
297     * Sets path info.
298     * <p>
299     * path and ref attributes will be set according to info
300     */
301    void setPathInfo(String parentPath, String name);
302
303    /**
304     * Tests if the document is locked.
305     * <p>
306     * Lock info is cached on the document for performance. Use {@link CoreSession#getLockInfo} to get the non-cached
307     * status.
308     *
309     * @return the lock key if the document is locked or null otherwise
310     */
311    boolean isLocked();
312
313    /**
314     * Sets a lock on the document.
315     *
316     * @return the lock info that was set
317     * @throws LockException if the document is already locked
318     * @since 5.4.2
319     */
320    Lock setLock() throws LockException;
321
322    /**
323     * Gets the lock info on the document.
324     * <p>
325     * Lock info is cached on the document for performance. Use {@link CoreSession#getLockInfo} to get the non-cached
326     * status.
327     *
328     * @return the lock info if the document is locked, or {@code null} otherwise
329     * @since 5.4.2
330     */
331    Lock getLockInfo();
332
333    /**
334     * Removes the lock on the document.
335     * <p>
336     * The caller principal should be the same as the one who set the lock or to belongs to the administrator group,
337     * otherwise an exception will be throw.
338     * <p>
339     * If the document was not locked, does nothing.
340     * <p>
341     * Returns the previous lock info.
342     *
343     * @return the removed lock info, or {@code null} if there was no lock
344     * @throws LockException if the document is locked by someone else
345     * @since 5.4.2
346     */
347    Lock removeLock() throws LockException;
348
349    /**
350     * Tests if the document is checked out.
351     * <p>
352     * A checked out document can be modified normally. A checked in document is identical to the last version that it
353     * created, and not modifiable.
354     * <p>
355     * Only applicable to documents that are live (not versions and not proxies).
356     *
357     * @return {@code true} if the document is checked out, {@code false} if it is checked in
358     * @since 5.4
359     */
360    boolean isCheckedOut();
361
362    /**
363     * Checks out a document.
364     * <p>
365     * A checked out document can be modified normally.
366     * <p>
367     * Only applicable to documents that are live (not versions and not proxies).
368     *
369     * @since 5.4
370     */
371    void checkOut();
372
373    /**
374     * Checks in a document and returns the created version.
375     * <p>
376     * A checked in document is identical to the last version that it created, and not modifiable.
377     * <p>
378     * Only applicable to documents that are live (not versions and not proxies).
379     *
380     * @param option whether to do create a new {@link VersioningOption#MINOR} or {@link VersioningOption#MAJOR} version
381     *            during check in
382     * @param checkinComment the checkin comment
383     * @return the version just created
384     * @since 5.4
385     */
386    DocumentRef checkIn(VersioningOption option, String checkinComment);
387
388    /**
389     * Returns the version label.
390     * <p>
391     * The label returned is computed by the VersioningService.
392     *
393     * @return the version label, or {@code null}
394     */
395    String getVersionLabel();
396
397    /**
398     * Returns the checkin comment if the document model is a version.
399     *
400     * @return the checkin comment, or {@code null}
401     * @since 5.4
402     */
403    String getCheckinComment();
404
405    /**
406     * Gets the version series id for this document.
407     * <p>
408     * All documents and versions derived by a check in or checkout from the same original document share the same
409     * version series id.
410     *
411     * @return the version series id
412     * @since 5.4
413     */
414    String getVersionSeriesId();
415
416    /**
417     * Checks if a document is the latest version in the version series.
418     *
419     * @since 5.4
420     */
421    boolean isLatestVersion();
422
423    /**
424     * Checks if a document is a major version.
425     *
426     * @since 5.4
427     */
428    boolean isMajorVersion();
429
430    /**
431     * Checks if a document is the latest major version in the version series.
432     *
433     * @since 5.4
434     */
435    boolean isLatestMajorVersion();
436
437    /**
438     * Checks if there is a checked out working copy for the version series of this document.
439     *
440     * @since 5.4
441     */
442    boolean isVersionSeriesCheckedOut();
443
444    /**
445     * Checks if the document is a record.
446     *
447     * @return {@code true} if the document is a record, {@code false} otherwise
448     * @since 11.1
449     */
450    default boolean isRecord() {
451        return false;
452    }
453
454    /**
455     * Gets the retention date for the document.
456     *
457     * @return the retention date, or {@value org.nuxeo.ecm.core.api.security.SecurityConstants#SET_RETENTION} for a
458     *         retention in the indeterminate future, or {@code null} if there is no retention date
459     * @see CoreSession#RETAIN_UNTIL_INDETERMINATE
460     * @see #isUnderRetentionOrLegalHold
461     * @since 11.1
462     */
463    default Calendar getRetainUntil() {
464        return null;
465    }
466
467    /**
468     * Checks if the document has a legal hold set.
469     *
470     * @return {@code true} if a legal hold has been set on the document, {@code false} otherwise
471     * @see #isUnderRetentionOrLegalHold
472     * @since 11.1
473     */
474    default boolean hasLegalHold() {
475        return false;
476    }
477
478    /**
479     * Checks if the document has a retention date in the future or has a legal hold.
480     *
481     * @return {@code true} if the document has a retention date in the future or if it has a legal hold, {@code false}
482     *         otherwise
483     * @see #getRetainUntil
484     * @see #hasLegalHold
485     * @since 11.1
486     */
487    default boolean isUnderRetentionOrLegalHold() {
488        return false;
489    }
490
491    /**
492     * Gets the access control policy (ACP) for this document.
493     * <p>
494     * Returns null if no security was defined on this document.
495     * <p>
496     * The ACP can be used to introspect or to evaluate user privileges on this document.
497     * <p>
498     * This is a wrapper for {@link CoreSession#getACP(DocumentRef)} but it is recommended since it caches the ACP for
499     * later usage.
500     *
501     * @return the security data model or null if none
502     */
503    ACP getACP();
504
505    /**
506     * Sets the ACP for this document model.
507     * <p>
508     * This is a wrapper for {@link CoreSession#setACP(DocumentRef, ACP, boolean)}
509     *
510     * @see CoreSession#setACP(DocumentRef, ACP, boolean)
511     * @param acp the ACP to set
512     * @param overwrite whether to overwrite the old ACP or not
513     */
514    void setACP(ACP acp, boolean overwrite);
515
516    /**
517     * Gets a property from the given schema.
518     * <p>
519     * The data model owning the property will be fetched from the server if not already fetched.
520     *
521     * @param schemaName the schema name
522     * @param name the property name
523     * @return the property value or null if no such property exists
524     */
525    Object getProperty(String schemaName, String name);
526
527    /**
528     * Gets a property object from the given schema.
529     *
530     * @param schema the schema name
531     * @param name the property name
532     * @return the property, or {@code null} if no such property exists
533     * @since 8.4
534     */
535    Property getPropertyObject(String schema, String name);
536
537    /**
538     * Sets the property value from the given schema.
539     * <p>
540     * This operation will not fetch the data model if not already fetched
541     *
542     * @param schemaName the schema name
543     * @param name the property name
544     * @param value the property value
545     */
546    void setProperty(String schemaName, String name, Object value);
547
548    /**
549     * Gets the values from the given data model as a map.
550     * <p>
551     * The operation will fetch the data model from the server if not already fetched.
552     *
553     * @param schemaName the data model schema name
554     * @return the values map
555     */
556    Map<String, Object> getProperties(String schemaName);
557
558    /**
559     * Sets values for the given data model.
560     * <p>
561     * This will not fetch the data model if not already fetched.
562     *
563     * @param schemaName the schema name
564     * @param data the values to set
565     */
566    void setProperties(String schemaName, Map<String, Object> data);
567
568    /**
569     * Checks if this document is in the trash.
570     *
571     * @return true if the document is in the trash, false otherwise.
572     * @since 10.1
573     */
574    boolean isTrashed();
575
576    /**
577     * Checks if this document is a folder.
578     *
579     * @return true if the document is a folder, false otherwise
580     */
581    boolean isFolder();
582
583    /**
584     * Checks if this document can have versions.
585     *
586     * @return true if the document can have versions, false otherwise
587     */
588    boolean isVersionable();
589
590    /**
591     * Checks if this document can be downloaded.
592     *
593     * @return true if the document has downloadable content, false otherwise
594     */
595    boolean isDownloadable();
596
597    /**
598     * Checks if this document is a version.
599     *
600     * @return true if the document is an older version of another document, false otherwise
601     */
602    boolean isVersion();
603
604    /**
605     * Checks if this document is a proxy.
606     *
607     * @return true if the document is a proxy false otherwise
608     */
609    boolean isProxy();
610
611    /**
612     * Checks if this document is immutable.
613     *
614     * @return {@code true} if the document is a version or a proxy to a version, {@code false} otherwise
615     * @since 1.6.1 (5.3.1)
616     */
617    boolean isImmutable();
618
619    /**
620     * Checks if the document has actual data to write (dirty parts).
621     *
622     * @since 5.5
623     */
624    boolean isDirty();
625
626    /**
627     * Method that implement the visitor pattern.
628     * <p>
629     * The visitor must return null to stop visiting children otherwise a context object that will be passed as the arg
630     * argument to children
631     *
632     * @param visitor the visitor to accept
633     * @param arg an argument passed to the visitor. This should be used by the visitor to carry on the visiting
634     *            context.
635     * @since 5.5
636     */
637    void accept(PropertyVisitor visitor, Object arg);
638
639    /**
640     * Adapts the document to the given interface.
641     * <p>
642     * Attention, the first computation will cache the adaptation result for later calls.
643     * </p>
644     *
645     * @param <T> the interface type to adapt to
646     * @param itf the interface class
647     * @return the adapted document
648     */
649    <T> T getAdapter(Class<T> itf);
650
651    /**
652     * Adapts the document to the given interface.
653     *
654     * @param <T> the interface type to adapt to
655     * @param itf the interface class
656     * @param refreshCache : readapt and stores in cache if already exists.
657     * @return the adapted document
658     */
659    <T> T getAdapter(Class<T> itf, boolean refreshCache);
660
661    /**
662     * Returns the life cycle of the document.
663     *
664     * @return the life cycle as a string
665     * @implNote See org.nuxeo.ecm.core.lifecycle package
666     */
667    String getCurrentLifeCycleState();
668
669    /**
670     * Returns the life cycle policy of the document.
671     *
672     * @return the life cycle policy
673     * @implNote See org.nuxeo.ecm.core.lifecycle package
674     */
675    String getLifeCyclePolicy();
676
677    /**
678     * Follows a given life cycle transition.
679     * <p>
680     * This will update the current life cycle of the document.
681     *
682     * @param transition the name of the transition to follow
683     * @return a boolean representing the status if the operation
684     */
685    boolean followTransition(String transition);
686
687    /**
688     * Gets the allowed state transitions for this document.
689     *
690     * @return a collection of state transitions as string
691     */
692    Collection<String> getAllowedStateTransitions();
693
694    /**
695     * Gets the context data associated to this document.
696     *
697     * @return a map of context data
698     */
699    Map<String, Serializable> getContextData();
700
701    /**
702     * Gets the context data using the default scope.
703     *
704     * @param key the context data key
705     * @return the value
706     */
707    Serializable getContextData(String key);
708
709    /**
710     * Sets a context data in the default scope.
711     *
712     * @param key the context data key
713     * @param value the value
714     */
715    void putContextData(String key, Serializable value);
716
717    /**
718     * Copies the context data from given document to this document.
719     */
720    void copyContextData(DocumentModel otherDocument);
721
722    /**
723     * Copies all the data from a source document.
724     */
725    void copyContent(DocumentModel sourceDoc);
726
727    /**
728     * Returns the name of the repository in which the document is stored.
729     *
730     * @return the repository name as a string.
731     */
732    String getRepositoryName();
733
734    /**
735     * Returns a cache key.
736     * <p>
737     * Cache key will be computed like this : <code>
738     *     docUUID + "-" + sessionId + "-" + timestamp
739     *   </code>
740     * <p>
741     * We will use the last modification time if present for the timestamp.
742     * <p>
743     * Since 5.6, the timestamp does not hold milliseconds anymore as some databases do not store them, which could
744     * interfere with cache key comparisons.
745     *
746     * @return the cache key as a string
747     */
748    String getCacheKey();
749
750    /**
751     * Returns the source document identifier.
752     * <p>
753     * This is useful when not interested about the repository UUID itself. Technically, this is the current version
754     * UUID.
755     *
756     * @return the source id as a string.
757     */
758    String getSourceId();
759
760    /**
761     * Checks if a property is prefetched.
762     *
763     * @param xpath the property xpath
764     * @return {@code true} if it is prefetched
765     * @since 5.5
766     * @deprecated since 10.1, will always return {@code false}
767     */
768    @Deprecated
769    boolean isPrefetched(String xpath);
770
771    /**
772     * Checks if a property is prefetched.
773     *
774     * @param schemaName the schema name
775     * @param name the property name
776     * @return {@code true} if it is prefetched
777     * @since 5.5
778     * @deprecated since 10.1, will always return {@code false}
779     */
780    @Deprecated
781    boolean isPrefetched(String schemaName, String name);
782
783    /**
784     * Used to set lifecycle state along with prefetching other properties.
785     */
786    void prefetchCurrentLifecycleState(String lifecycle);
787
788    /**
789     * Used to set lifecycle policy along with prefetching other properties.
790     */
791    void prefetchLifeCyclePolicy(String lifeCyclePolicy);
792
793    boolean isLifeCycleLoaded();
794
795    /**
796     * Gets system property of the specified type. This is not a lazy loaded property, thus the request is made directly
797     * to the server. This is needed as some critical system properties might be changed directly in the core.
798     */
799    <T extends Serializable> T getSystemProp(String systemProperty, Class<T> type);
800
801    /**
802     * Get a document part given its schema name
803     *
804     * @param schema the schema
805     * @return the document aprt or null if none exists for that schema
806     * @deprecated since 8.4, use direct {@link Property} getters instead
807     * @see #getPropertyObject
808     * @see #getPropertyObjects
809     */
810    @Deprecated
811    DocumentPart getPart(String schema);
812
813    /**
814     * Gets this document's parts.
815     *
816     * @deprecated since 8.4, use direct {@link Property} getters instead
817     * @see #getSchemas
818     * @see #getPropertyObject
819     * @see #getPropertyObjects
820     */
821    @Deprecated
822    DocumentPart[] getParts();
823
824    /**
825     * Gets the {@link Property} objects for the given schema.
826     * <p>
827     * An empty list is returned if the document doesn't have the schema.
828     *
829     * @param schema the schema
830     * @return the properties
831     * @since 8.4
832     */
833    Collection<Property> getPropertyObjects(String schema);
834
835    /**
836     * Gets a property given a xpath.
837     * <p>
838     * Note that what's called xpath in this context is not an actual XPath as specified by the w3c. Main differences
839     * are that in our xpath:
840     * <ul>
841     * <li>Indexes start at 0 instead of 1</li>
842     * <li>You can express {@code foo/bar[i]/baz} as {@code foo/i/baz}</li>
843     * </ul>
844     * The latter is possible because in Nuxeo lists of complex elements are homogenous, so the name of the second-level
845     * element is implied.
846     */
847    Property getProperty(String xpath) throws PropertyException;
848
849    /**
850     * Gets a property value given a xpath.
851     * <p>
852     * Note that what's called xpath in this context is not an actual XPath as specified by the w3c. Main differences
853     * are that in our xpath:
854     * <ul>
855     * <li>Indexes start at 0 instead of 1</li>
856     * <li>You can express {@code foo/bar[i]/baz} as {@code foo/i/baz}</li>
857     * </ul>
858     * The latter is possible because in Nuxeo lists of complex elements are homogenous, so the name of the second-level
859     * element is implied.
860     */
861    Serializable getPropertyValue(String xpath) throws PropertyException;
862
863    /**
864     * Sets a property value given a xpath.
865     */
866    void setPropertyValue(String xpath, Serializable value) throws PropertyException;
867
868    /**
869     * Clears any prefetched or cached document data.
870     * <p>
871     * This will force the document to lazily update its data when required.
872     */
873    void reset();
874
875    /**
876     * Refresh document data from server.
877     * <p>
878     * The data models will be removed and all prefetch and system data will be refreshed from the server
879     * <p>
880     * The refreshed data contains:
881     * <ul>
882     * <li>document life cycle
883     * <li>document lock state, acp if required
884     * <li>acp if required - otherwise acp info will be cleared so that it will be refetched in lazy way
885     * <li>document parts if required - otherwise parts data will be removed to be refreshed lazy
886     * </ul>
887     * The refresh flags are:
888     * <ul>
889     * <li>{@link DocumentModel#REFRESH_STATE}
890     * <li>{@link DocumentModel#REFRESH_ACP_IF_LOADED}
891     * <li>{@link DocumentModel#REFRESH_ACP_LAZY}
892     * <li>{@link DocumentModel#REFRESH_ACP}
893     * <li>{@link DocumentModel#REFRESH_CONTENT_IF_LOADED}
894     * <li>{@link DocumentModel#REFRESH_CONTENT_LAZY}
895     * <li>{@link DocumentModel#REFRESH_CONTENT}
896     * <li>{@link DocumentModel#REFRESH_DEFAULT} same as REFRESH_STATE | REFRESH_DEFAULT | REFRESH_ACP_IF_LOADED |
897     * REFRESH_CONTENT_IF_LOADED
898     * <li>{@link DocumentModel#REFRESH_ALL} same as REFRESH_STATE | REFRESH_PREFTECH | REFRESH_ACP | REFRESH_CONTENT
899     * </ul>
900     * If XX_IF_LOADED is used then XX will be refreshed only if already loaded in the document - otherwise a lazy
901     * refresh will be done
902     *
903     * @param refreshFlags the refresh flags
904     * @param schemas the document parts (schemas) that should be refreshed now
905     */
906    void refresh(int refreshFlags, String[] schemas);
907
908    /** Info fetched internally during a refresh. */
909    class DocumentModelRefresh {
910
911        public String lifeCycleState;
912
913        public String lifeCyclePolicy;
914
915        public boolean isCheckedOut;
916
917        public boolean isLatestVersion;
918
919        public boolean isMajorVersion;
920
921        public boolean isLatestMajorVersion;
922
923        public boolean isVersionSeriesCheckedOut;
924
925        public String versionSeriesId;
926
927        public String checkinComment;
928
929        public ACP acp;
930
931        public Set<String> instanceFacets;
932
933        public DocumentPart[] documentParts;
934
935        public boolean isTrashed;
936
937        public boolean isRecord;
938
939        public Calendar retainUntil;
940
941        public boolean hasLegalHold;
942    }
943
944    /**
945     * Same as {@code DocumentModel.refresh(REFRESH_DEFAULT)}.
946     */
947    void refresh();
948
949    /**
950     * Clone operation. Must be made public instead of just protected as in Object.
951     */
952    DocumentModel clone() throws CloneNotSupportedException;
953
954    /**
955     * Gets the current change token for this document.
956     * <p>
957     * The change token is an opaque string which is modified every time the document is changed.
958     * <p>
959     * Before saving a document through {@link CoreSession#saveDocument} it's possible to pass an expected change token
960     * in the document context data through {@code doc.putContextData(CoreSession.CHANGE_TOKEN, expectedChangeToken)}.
961     * If the change token does not match the stored one, it means that a concurrent update happened, and a
962     * {@link org.nuxeo.ecm.core.api.ConcurrentUpdateException ConcurrentUpdateException} will be thrown.
963     *
964     * @return the change token
965     * @since 5.5
966     * @see #putContextData
967     * @see CoreSession#CHANGE_TOKEN
968     * @see CoreSession#getChangeToken
969     */
970    String getChangeToken();
971
972    /**
973     * Gets the fulltext extracted from the binary fields.
974     *
975     * @since 5.9.3
976     */
977    Map<String, String> getBinaryFulltext();
978
979    /**
980     * @param xpath the property xpath
981     * @return A {@link PropertyObjectResolver} to manage the property reference to external entities, null if this
982     *         property's type has no resolver.
983     * @since 7.1
984     */
985    PropertyObjectResolver getObjectResolver(String xpath);
986
987}