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     * Loads a {@link DocumentPart} from storage.
259     * <p>
260     * Reading data is done by {@link DocumentPart} because of per-proxy schemas.
261     */
262    void readDocumentPart(DocumentPart dp) throws PropertyException;
263
264    /**
265     * Reads a set of prefetched fields.
266     * <p>
267     * Reading data is done by {@link ComplexType} because of per-proxy schemas.
268     *
269     * @since 5.9.4
270     */
271    Map<String, Serializable> readPrefetch(ComplexType complexType, Set<String> xpaths) throws PropertyException;
272
273    /**
274     * Context passed to write operations to optionally record things to do at {@link #flush} time.
275     *
276     * @since 7.3
277     */
278    interface WriteContext {
279        /**
280         * Gets the recorded changed xpaths.
281         */
282        Set<String> getChanges();
283
284        /**
285         * Flushes recorded write operations.
286         *
287         * @param doc the base document being written
288         */
289        void flush(Document doc);
290    }
291
292    /**
293     * Gets a write context for the current document.
294     *
295     * @since 7.3
296     */
297    WriteContext getWriteContext();
298
299    /**
300     * Writes a {@link DocumentPart} to storage.
301     * <p>
302     * Writing data is done by {@link DocumentPart} because of per-proxy schemas.
303     *
304     * @return {@code true} if something changed
305     */
306    boolean writeDocumentPart(DocumentPart dp, WriteContext writeContext) throws PropertyException;
307
308    /**
309     * Gets the facets available on this document (from the type and the instance facets).
310     *
311     * @return the facets
312     * @since 5.4.2
313     */
314    Set<String> getAllFacets();
315
316    /**
317     * Gets the facets defined on this document instance. The type facets are not returned.
318     *
319     * @return the facets
320     * @since 5.4.2
321     */
322    String[] getFacets();
323
324    /**
325     * Checks whether this document has a given facet, either from its type or added on the instance.
326     *
327     * @param facet the facet name
328     * @return {@code true} if the document has the facet
329     * @since 5.4.2
330     */
331    boolean hasFacet(String facet);
332
333    /**
334     * Adds a facet to this document.
335     * <p>
336     * Does nothing if the facet was already present on the document.
337     *
338     * @param facet the facet name
339     * @return {@code true} if the facet was added, or {@code false} if it is already present
340     * @throws IllegalArgumentException if the facet does not exist
341     * @since 5.4.2
342     */
343    boolean addFacet(String facet);
344
345    /**
346     * Removes a facet from this document.
347     * <p>
348     * It's not possible to remove a facet coming from the document type.
349     *
350     * @param facet the facet name
351     * @return {@code true} if the facet was removed, or {@code false} if it isn't present or is present on the type or
352     *         does not exit
353     * @since 5.4.2
354     */
355    boolean removeFacet(String facet);
356
357    /**
358     * Sets a lock on this document.
359     *
360     * @param lock the lock to set
361     * @return {@code null} if locking succeeded, or the existing lock if locking failed
362     */
363    Lock setLock(Lock lock);
364
365    /**
366     * Removes a lock from this document.
367     *
368     * @param the owner to check, or {@code null} for no check
369     * @return {@code null} if there was no lock or if removal succeeded, or a lock if it blocks removal due to owner
370     *         mismatch
371     */
372    Lock removeLock(String owner);
373
374    /**
375     * Gets the lock if one set on this document.
376     *
377     * @return the lock, or {@code null} if no lock is set
378     */
379    Lock getLock();
380
381    /**
382     * Gets a child document given its name.
383     * <p>
384     * Throws {@link DocumentNotFoundException} if the document could not be found.
385     *
386     * @param name the name of the child to retrieve
387     * @return the child if exists
388     * @throws DocumentNotFoundException if the child does not exist
389     */
390    Document getChild(String name);
391
392    /**
393     * Gets the children of the document.
394     * <p>
395     * Returns an empty list for non-folder documents.
396     *
397     * @return the children
398     */
399    List<Document> getChildren();
400
401    /**
402     * Gets a list of the children ids.
403     * <p>
404     * Returns an empty list for non-folder documents.
405     *
406     * @return a list of children ids.
407     * @since 1.4.1
408     */
409    List<String> getChildrenIds();
410
411    /**
412     * Checks whether this document has a child of the given name.
413     * <p>
414     * Returns {@code false} for non-folder documents.
415     *
416     * @param name the name of the child to check
417     * @return {@code true} if the child exists, {@code false} otherwise
418     */
419    boolean hasChild(String name);
420
421    /**
422     * Tests if the document has any children.
423     * <p>
424     * Returns {@code false} for non-folder documents.
425     *
426     * @return {@code true} if the document has children, {@code false} otherwise
427     */
428    boolean hasChildren();
429
430    /**
431     * Creates a new child document of the given type.
432     * <p>
433     * Throws an error if this document is not a folder.
434     *
435     * @param name the name of the new child to create
436     * @param typeName the type of the child to create
437     * @return the newly created document
438     */
439    Document addChild(String name, String typeName);
440
441    /**
442     * Orders the given source child before the destination child.
443     * <p>
444     * Both source and destination must be names that point to child documents of this document. The source document
445     * will be placed before the destination one. If destination is {@code null}, the source document will be appended
446     * at the end of the children list.
447     *
448     * @param src the document to move
449     * @param dest the document before which to place the source document
450     */
451    void orderBefore(String src, String dest);
452
453    /**
454     * Creates a new version.
455     *
456     * @param label the version label
457     * @param checkinComment the checkin comment
458     * @return the created version
459     */
460    Document checkIn(String label, String checkinComment);
461
462    void checkOut();
463
464    /**
465     * Gets the list of version ids for this document.
466     *
467     * @return the list of version ids
468     * @since 1.4.1
469     */
470    List<String> getVersionsIds();
471
472    /**
473     * Gets the versions for this document.
474     *
475     * @return the versions of the document, or an empty list if there are no versions
476     */
477    List<Document> getVersions();
478
479    /**
480     * Gets the last version of this document.
481     * <p>
482     * Returns {@code null} if there is no version at all.
483     *
484     * @return the last version, or {@code null} if there is no version
485     */
486    Document getLastVersion();
487
488    /**
489     * Gets the source for this document.
490     * <p>
491     * For a version, it's the working copy.
492     * <p>
493     * For a proxy, it's the version the proxy points to.
494     *
495     * @return the source document
496     */
497    Document getSourceDocument();
498
499    /**
500     * Replaces this document's content with the version specified.
501     *
502     * @param version the version to replace with
503     */
504    void restore(Document version);
505
506    /**
507     * Gets a version of this document, given its label.
508     *
509     * @param label the version label
510     * @return the version
511     */
512    Document getVersion(String label);
513
514    /**
515     * Checks whether this document is a version document.
516     *
517     * @return {@code true} if it's a version, {@code false} otherwise
518     */
519    boolean isVersion();
520
521    /**
522     * Gets the version to which a checked in document is linked.
523     * <p>
524     * Returns {@code null} for a checked out document or a version or a proxy.
525     *
526     * @return the version, or {@code null}
527     */
528    Document getBaseVersion();
529
530    /**
531     * Checks whether this document is checked out.
532     *
533     * @return {@code true} if the document is checked out, or {@code false} otherwise
534     */
535    boolean isCheckedOut();
536
537    /**
538     * Gets the version creation date of this document if it's a version or a proxy.
539     *
540     * @return the version creation date, or {@code null} if it's not a version or a proxy
541     */
542    Calendar getVersionCreationDate();
543
544    /**
545     * Gets the version check in comment of this document if it's a version or a proxy.
546     *
547     * @return the check in comment, or {@code null} if it's not a version or a proxy
548     */
549    String getCheckinComment();
550
551    /**
552     * Gets the version series id.
553     *
554     * @return the version series id
555     */
556    String getVersionSeriesId();
557
558    /**
559     * Gets the version label.
560     *
561     * @return the version label
562     */
563    String getVersionLabel();
564
565    /**
566     * Checks whether this document is the latest version.
567     *
568     * @return {@code true} if this is the latest version, or {@code false} otherwise
569     */
570    boolean isLatestVersion();
571
572    /**
573     * Checks whether this document is a major version.
574     *
575     * @return {@code true} if this is a major version, or {@code false} otherwise
576     */
577    boolean isMajorVersion();
578
579    /**
580     * Checks whether this document is the latest major version.
581     *
582     * @return {@code true} if this is the latest major version, or {@code false} otherwise
583     */
584    boolean isLatestMajorVersion();
585
586    /**
587     * Checks if there is a checked out working copy for the version series of this document.
588     *
589     * @return {@code true} if there is a checked out working copy
590     */
591    boolean isVersionSeriesCheckedOut();
592
593    /**
594     * Gets the working copy for this document.
595     *
596     * @return the working copy
597     */
598    Document getWorkingCopy();
599
600    /**
601     * Gets the document (version or live document) to which this proxy points.
602     */
603    Document getTargetDocument();
604
605    /**
606     * Sets the document (version or live document) to which this proxy points.
607     */
608    void setTargetDocument(Document target);
609
610}