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