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