001/*
002 * (C) Copyright 2006-2014 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 *     Julien Anguenot
019 *     Florent Guillaume
020 */
021package org.nuxeo.ecm.core.model;
022
023import java.io.Serializable;
024import java.util.Calendar;
025import java.util.Collection;
026import java.util.List;
027import java.util.Map;
028import java.util.Set;
029import java.util.function.Consumer;
030
031import org.nuxeo.ecm.core.api.Blob;
032import org.nuxeo.ecm.core.api.DocumentNotFoundException;
033import org.nuxeo.ecm.core.api.LifeCycleException;
034import org.nuxeo.ecm.core.api.Lock;
035import org.nuxeo.ecm.core.api.PropertyException;
036import org.nuxeo.ecm.core.api.model.DocumentPart;
037import org.nuxeo.ecm.core.schema.DocumentType;
038import org.nuxeo.ecm.core.schema.types.ComplexType;
039
040/**
041 * A low-level document from a {@link Session}.
042 */
043public interface Document {
044
045    /**
046     * Gets the session that owns this document.
047     *
048     * @return the session
049     */
050    Session getSession();
051
052    /**
053     * Gets the name of this document.
054     *
055     * @return the document name
056     */
057    String getName();
058
059    /**
060     * Gets the document's position in its containing folder (if ordered).
061     *
062     * @return the position
063     * @since 6.0
064     */
065    Long getPos();
066
067    /**
068     * Gets this document's UUID.
069     *
070     * @return the document UUID
071     */
072    String getUUID();
073
074    /**
075     * Gets the parent document, or {@code null} if this is the root document.
076     *
077     * @return the parent document, or {@code null}
078     */
079    Document getParent();
080
081    /**
082     * Gets the type of this document.
083     *
084     * @return the document type
085     */
086    DocumentType getType();
087
088    /**
089     * Gets the path of this document.
090     *
091     * @return the path
092     */
093    String getPath();
094
095    /**
096     * Sets a simple property value.
097     * <p>
098     * For more generic properties described by an xpath, use {@link #setValue} instead.
099     *
100     * @param name the name of the property to set
101     * @param value the value to set
102     * @see #setValue
103     */
104    void setPropertyValue(String name, Serializable value);
105
106    /**
107     * Sets a property value.
108     * <p>
109     * The xpath may point to a partial path, in which case the value may be a complex {@link List} or {@link Map}.
110     *
111     * @param xpath the xpath of the property to set
112     * @param value the value to set
113     * @throws PropertyException if the property does not exist or the value is of the wrong type
114     * @since 7.3
115     */
116    void setValue(String xpath, Object value) throws PropertyException;
117
118    /**
119     * Gets a simple property value.
120     * <p>
121     * For more generic properties described by an xpath, use {@link #getValue} instead.
122     *
123     * @param name the name of the property to get
124     * @return the property value or {@code null} if the property is not set
125     * @see #getValue
126     */
127    Serializable getPropertyValue(String name);
128
129    /**
130     * Gets a property value.
131     * <p>
132     * The xpath may point to a partial path, in which case the value may be a complex {@link List} or {@link Map}.
133     *
134     * @param xpath the xpath of the property to set
135     * @return the property value or {@code null} if the property is not set
136     * @throws PropertyException if the property does not exist
137     */
138    Object getValue(String xpath) throws PropertyException;
139
140    /**
141     * An accessor that can read or write a blob and know its xpath.
142     *
143     * @since 7.3
144     */
145    interface BlobAccessor {
146        /** Gets the blob's xpath. */
147        String getXPath();
148
149        /** Gets the blob. */
150        Blob getBlob();
151
152        /** Sets the blob. */
153        void setBlob(Blob blob);
154    }
155
156    /**
157     * Visits all the blobs of this document and calls the passed blob visitor on each one.
158     *
159     * @since 7.3
160     */
161    void visitBlobs(Consumer<BlobAccessor> blobVisitor) throws PropertyException;
162
163    /**
164     * Checks whether this document is a folder.
165     *
166     * @return {@code true} if the document is a folder, {@code false} otherwise
167     */
168    boolean isFolder();
169
170    /**
171     * Sets this document as readonly or not.
172     *
173     * @since 5.9.2
174     */
175    void setReadOnly(boolean readonly);
176
177    /**
178     * Checks whether this document is readonly or not.
179     *
180     * @since 5.9.2
181     */
182    boolean isReadOnly();
183
184    /**
185     * Removes this document and all its children, if any.
186     */
187    void remove();
188
189    /**
190     * Gets the life cycle state of this document.
191     *
192     * @return the life cycle state
193     */
194    String getLifeCycleState();
195
196    /**
197     * Sets the life cycle state of this document.
198     *
199     * @param state the life cycle state
200     */
201    void setCurrentLifeCycleState(String state);
202
203    /**
204     * Gets the life cycle policy of this document.
205     *
206     * @return the life cycle policy
207     */
208    String getLifeCyclePolicy();
209
210    /**
211     * Sets the life cycle policy of this document.
212     *
213     * @param policy the life cycle policy
214     */
215    void setLifeCyclePolicy(String policy);
216
217    /**
218     * Follows a given life cycle transition.
219     * <p>
220     * This will update the life cycle state of the document.
221     *
222     * @param transition the name of the transition to follow
223     */
224    void followTransition(String transition) throws LifeCycleException;
225
226    /**
227     * Returns the allowed state transitions for this document.
228     *
229     * @return a collection of state transitions
230     */
231    Collection<String> getAllowedStateTransitions();
232
233    /**
234     * Checks whether or not this document is a proxy.
235     *
236     * @return {@code true} if this document is a proxy, {@code false} otherwise
237     */
238    boolean isProxy();
239
240    /**
241     * Gets the repository in which the document lives.
242     *
243     * @return the repository name.
244     */
245    String getRepositoryName();
246
247    /**
248     * Sets a system property.
249     */
250    void setSystemProp(String name, Serializable value);
251
252    /**
253     * Gets a system property.
254     */
255    <T extends Serializable> T getSystemProp(String name, Class<T> type);
256
257    /**
258     * Gets the current change token for this document.
259     *
260     * @return the change token
261     * @since 9.1
262     */
263    String getChangeToken();
264
265    /**
266     * Validates that the passed user-visible change token is compatible with the one for this document.
267     *
268     * @return {@code false} if the change token is not valid
269     * @since 9.2
270     */
271    boolean validateUserVisibleChangeToken(String changeToken);
272
273    /**
274     * Marks the document as being modified by a user change.
275     * <p>
276     * This causes an additional change token increment and check during save.
277     *
278     * @since 9.2
279     */
280    void markUserChange();
281
282    /**
283     * Loads a {@link DocumentPart} from storage.
284     * <p>
285     * Reading data is done by {@link DocumentPart} because of per-proxy schemas.
286     */
287    void readDocumentPart(DocumentPart dp) throws PropertyException;
288
289    /**
290     * Reads a set of prefetched fields.
291     * <p>
292     * Reading data is done by {@link ComplexType} because of per-proxy schemas.
293     *
294     * @since 5.9.4
295     */
296    Map<String, Serializable> readPrefetch(ComplexType complexType, Set<String> xpaths) throws PropertyException;
297
298    /**
299     * Context passed to write operations to optionally record things to do at {@link #flush} time.
300     *
301     * @since 7.3
302     */
303    interface WriteContext {
304        /**
305         * Gets the recorded changed xpaths.
306         */
307        Set<String> getChanges();
308
309        /**
310         * Flushes recorded write operations.
311         *
312         * @param doc the base document being written
313         */
314        void flush(Document doc);
315    }
316
317    /**
318     * Gets a write context for the current document.
319     *
320     * @since 7.3
321     */
322    WriteContext getWriteContext();
323
324    /**
325     * Writes a {@link DocumentPart} to storage.
326     * <p>
327     * Writing data is done by {@link DocumentPart} because of per-proxy schemas.
328     *
329     * @return {@code true} if something changed
330     */
331    boolean writeDocumentPart(DocumentPart dp, WriteContext writeContext) throws PropertyException;
332
333    /**
334     * Gets the facets available on this document (from the type and the instance facets).
335     *
336     * @return the facets
337     * @since 5.4.2
338     */
339    Set<String> getAllFacets();
340
341    /**
342     * Gets the facets defined on this document instance. The type facets are not returned.
343     *
344     * @return the facets
345     * @since 5.4.2
346     */
347    String[] getFacets();
348
349    /**
350     * Checks whether this document has a given facet, either from its type or added on the instance.
351     *
352     * @param facet the facet name
353     * @return {@code true} if the document has the facet
354     * @since 5.4.2
355     */
356    boolean hasFacet(String facet);
357
358    /**
359     * Adds a facet to this document.
360     * <p>
361     * Does nothing if the facet was already present on the document.
362     *
363     * @param facet the facet name
364     * @return {@code true} if the facet was added, or {@code false} if it is already present
365     * @throws IllegalArgumentException if the facet does not exist
366     * @since 5.4.2
367     */
368    boolean addFacet(String facet);
369
370    /**
371     * Removes a facet from this document.
372     * <p>
373     * It's not possible to remove a facet coming from the document type.
374     *
375     * @param facet the facet name
376     * @return {@code true} if the facet was removed, or {@code false} if it isn't present or is present on the type or
377     *         does not exit
378     * @since 5.4.2
379     */
380    boolean removeFacet(String facet);
381
382    /**
383     * Sets a lock on this document.
384     *
385     * @param lock the lock to set
386     * @return {@code null} if locking succeeded, or the existing lock if locking failed
387     */
388    Lock setLock(Lock lock);
389
390    /**
391     * Removes a lock from this document.
392     *
393     * @param the owner to check, or {@code null} for no check
394     * @return {@code null} if there was no lock or if removal succeeded, or a lock if it blocks removal due to owner
395     *         mismatch
396     */
397    Lock removeLock(String owner);
398
399    /**
400     * Gets the lock if one set on this document.
401     *
402     * @return the lock, or {@code null} if no lock is set
403     */
404    Lock getLock();
405
406    /**
407     * Gets a child document given its name.
408     * <p>
409     * Throws {@link DocumentNotFoundException} if the document could not be found.
410     *
411     * @param name the name of the child to retrieve
412     * @return the child if exists
413     * @throws DocumentNotFoundException if the child does not exist
414     */
415    Document getChild(String name);
416
417    /**
418     * Gets the children of the document.
419     * <p>
420     * Returns an empty list for non-folder documents.
421     *
422     * @return the children
423     */
424    List<Document> getChildren();
425
426    /**
427     * Gets a list of the children ids.
428     * <p>
429     * Returns an empty list for non-folder documents.
430     *
431     * @return a list of children ids.
432     * @since 1.4.1
433     */
434    List<String> getChildrenIds();
435
436    /**
437     * Checks whether this document has a child of the given name.
438     * <p>
439     * Returns {@code false} for non-folder documents.
440     *
441     * @param name the name of the child to check
442     * @return {@code true} if the child exists, {@code false} otherwise
443     */
444    boolean hasChild(String name);
445
446    /**
447     * Tests if the document has any children.
448     * <p>
449     * Returns {@code false} for non-folder documents.
450     *
451     * @return {@code true} if the document has children, {@code false} otherwise
452     */
453    boolean hasChildren();
454
455    /**
456     * Creates a new child document of the given type.
457     * <p>
458     * Throws an error if this document is not a folder.
459     *
460     * @param name the name of the new child to create
461     * @param typeName the type of the child to create
462     * @return the newly created document
463     */
464    Document addChild(String name, String typeName);
465
466    /**
467     * Orders the given source child before the destination child.
468     * <p>
469     * Both source and destination must be names that point to child documents of this document. The source document
470     * will be placed before the destination one. If destination is {@code null}, the source document will be appended
471     * at the end of the children list.
472     *
473     * @param src the document to move
474     * @param dest the document before which to place the source document
475     */
476    void orderBefore(String src, String dest);
477
478    /**
479     * Creates a new version.
480     *
481     * @param label the version label
482     * @param checkinComment the checkin comment
483     * @return the created version
484     */
485    Document checkIn(String label, String checkinComment);
486
487    void checkOut();
488
489    /**
490     * Gets the list of version ids for this document.
491     *
492     * @return the list of version ids
493     * @since 1.4.1
494     */
495    List<String> getVersionsIds();
496
497    /**
498     * Gets the versions for this document.
499     *
500     * @return the versions of the document, or an empty list if there are no versions
501     */
502    List<Document> getVersions();
503
504    /**
505     * Gets the last version of this document.
506     * <p>
507     * Returns {@code null} if there is no version at all.
508     *
509     * @return the last version, or {@code null} if there is no version
510     */
511    Document getLastVersion();
512
513    /**
514     * Gets the source for this document.
515     * <p>
516     * For a version, it's the working copy.
517     * <p>
518     * For a proxy, it's the version the proxy points to.
519     *
520     * @return the source document
521     */
522    Document getSourceDocument();
523
524    /**
525     * Replaces this document's content with the version specified.
526     *
527     * @param version the version to replace with
528     */
529    void restore(Document version);
530
531    /**
532     * Gets a version of this document, given its label.
533     *
534     * @param label the version label
535     * @return the version
536     */
537    Document getVersion(String label);
538
539    /**
540     * Checks whether this document is a version document.
541     *
542     * @return {@code true} if it's a version, {@code false} otherwise
543     */
544    boolean isVersion();
545
546    /**
547     * Gets the version to which a checked in document is linked.
548     * <p>
549     * Returns {@code null} for a checked out document or a version or a proxy.
550     *
551     * @return the version, or {@code null}
552     */
553    Document getBaseVersion();
554
555    /**
556     * Checks whether this document is checked out.
557     *
558     * @return {@code true} if the document is checked out, or {@code false} otherwise
559     */
560    boolean isCheckedOut();
561
562    /**
563     * Gets the version creation date of this document if it's a version or a proxy.
564     *
565     * @return the version creation date, or {@code null} if it's not a version or a proxy
566     */
567    Calendar getVersionCreationDate();
568
569    /**
570     * Gets the version check in comment of this document if it's a version or a proxy.
571     *
572     * @return the check in comment, or {@code null} if it's not a version or a proxy
573     */
574    String getCheckinComment();
575
576    /**
577     * Gets the version series id.
578     *
579     * @return the version series id
580     */
581    String getVersionSeriesId();
582
583    /**
584     * Gets the version label.
585     *
586     * @return the version label
587     */
588    String getVersionLabel();
589
590    /**
591     * Checks whether this document is the latest version.
592     *
593     * @return {@code true} if this is the latest version, or {@code false} otherwise
594     */
595    boolean isLatestVersion();
596
597    /**
598     * Checks whether this document is a major version.
599     *
600     * @return {@code true} if this is a major version, or {@code false} otherwise
601     */
602    boolean isMajorVersion();
603
604    /**
605     * Checks whether this document is the latest major version.
606     *
607     * @return {@code true} if this is the latest major version, or {@code false} otherwise
608     */
609    boolean isLatestMajorVersion();
610
611    /**
612     * Checks if there is a checked out working copy for the version series of this document.
613     *
614     * @return {@code true} if there is a checked out working copy
615     */
616    boolean isVersionSeriesCheckedOut();
617
618    /**
619     * Gets the working copy for this document.
620     *
621     * @return the working copy
622     */
623    Document getWorkingCopy();
624
625    /**
626     * Gets the document (version or live document) to which this proxy points.
627     */
628    Document getTargetDocument();
629
630    /**
631     * Sets the document (version or live document) to which this proxy points.
632     */
633    void setTargetDocument(Document target);
634
635}