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     * Checks whether this document is under active retention.
191     *
192     * @since 9.3
193     */
194    boolean isRetentionActive();
195
196    /**
197     * Sets or unsets this document as under active retention.
198     *
199     * @since 9.3
200     */
201    void setRetentionActive(boolean retentionActive);
202
203    /**
204     * Gets the life cycle state of this document.
205     *
206     * @return the life cycle state
207     */
208    String getLifeCycleState();
209
210    /**
211     * Sets the life cycle state of this document.
212     *
213     * @param state the life cycle state
214     */
215    void setCurrentLifeCycleState(String state);
216
217    /**
218     * Gets the life cycle policy of this document.
219     *
220     * @return the life cycle policy
221     */
222    String getLifeCyclePolicy();
223
224    /**
225     * Sets the life cycle policy of this document.
226     *
227     * @param policy the life cycle policy
228     */
229    void setLifeCyclePolicy(String policy);
230
231    /**
232     * Follows a given life cycle transition.
233     * <p>
234     * This will update the life cycle state of the document.
235     *
236     * @param transition the name of the transition to follow
237     */
238    void followTransition(String transition) throws LifeCycleException;
239
240    /**
241     * Returns the allowed state transitions for this document.
242     *
243     * @return a collection of state transitions
244     */
245    Collection<String> getAllowedStateTransitions();
246
247    /**
248     * Checks whether or not this document is a proxy.
249     *
250     * @return {@code true} if this document is a proxy, {@code false} otherwise
251     */
252    boolean isProxy();
253
254    /**
255     * Gets the repository in which the document lives.
256     *
257     * @return the repository name.
258     */
259    String getRepositoryName();
260
261    /**
262     * Sets a system property.
263     */
264    void setSystemProp(String name, Serializable value);
265
266    /**
267     * Gets a system property.
268     */
269    <T extends Serializable> T getSystemProp(String name, Class<T> type);
270
271    /**
272     * Gets the current change token for this document.
273     *
274     * @return the change token
275     * @since 9.1
276     */
277    String getChangeToken();
278
279    /**
280     * Validates that the passed user-visible change token is compatible with the one for this document.
281     *
282     * @return {@code false} if the change token is not valid
283     * @since 9.2
284     */
285    boolean validateUserVisibleChangeToken(String changeToken);
286
287    /**
288     * Marks the document as being modified by a user change.
289     * <p>
290     * This causes an additional change token increment and check during save.
291     *
292     * @since 9.2
293     */
294    void markUserChange();
295
296    /**
297     * Loads a {@link DocumentPart} from storage.
298     * <p>
299     * Reading data is done by {@link DocumentPart} because of per-proxy schemas.
300     */
301    void readDocumentPart(DocumentPart dp) throws PropertyException;
302
303    /**
304     * Reads a set of prefetched fields.
305     * <p>
306     * Reading data is done by {@link ComplexType} because of per-proxy schemas.
307     *
308     * @since 5.9.4
309     */
310    Map<String, Serializable> readPrefetch(ComplexType complexType, Set<String> xpaths) throws PropertyException;
311
312    /**
313     * Context passed to write operations to optionally record things to do at {@link #flush} time.
314     *
315     * @since 7.3
316     */
317    interface WriteContext {
318        /**
319         * Gets the recorded changed xpaths.
320         */
321        Set<String> getChanges();
322
323        /**
324         * Flushes recorded write operations.
325         *
326         * @param doc the base document being written
327         */
328        void flush(Document doc);
329    }
330
331    /**
332     * Gets a write context for the current document.
333     *
334     * @since 7.3
335     */
336    WriteContext getWriteContext();
337
338    /**
339     * Writes a {@link DocumentPart} to storage.
340     * <p>
341     * Writing data is done by {@link DocumentPart} because of per-proxy schemas.
342     *
343     * @return {@code true} if something changed
344     */
345    boolean writeDocumentPart(DocumentPart dp, WriteContext writeContext) throws PropertyException;
346
347    /**
348     * Gets the facets available on this document (from the type and the instance facets).
349     *
350     * @return the facets
351     * @since 5.4.2
352     */
353    Set<String> getAllFacets();
354
355    /**
356     * Gets the facets defined on this document instance. The type facets are not returned.
357     *
358     * @return the facets
359     * @since 5.4.2
360     */
361    String[] getFacets();
362
363    /**
364     * Checks whether this document has a given facet, either from its type or added on the instance.
365     *
366     * @param facet the facet name
367     * @return {@code true} if the document has the facet
368     * @since 5.4.2
369     */
370    boolean hasFacet(String facet);
371
372    /**
373     * Adds a facet to this document.
374     * <p>
375     * Does nothing if the facet was already present on the document.
376     *
377     * @param facet the facet name
378     * @return {@code true} if the facet was added, or {@code false} if it is already present
379     * @throws IllegalArgumentException if the facet does not exist
380     * @since 5.4.2
381     */
382    boolean addFacet(String facet);
383
384    /**
385     * Removes a facet from this document.
386     * <p>
387     * It's not possible to remove a facet coming from the document type.
388     *
389     * @param facet the facet name
390     * @return {@code true} if the facet was removed, or {@code false} if it isn't present or is present on the type or
391     *         does not exit
392     * @since 5.4.2
393     */
394    boolean removeFacet(String facet);
395
396    /**
397     * Sets a lock on this document.
398     *
399     * @param lock the lock to set
400     * @return {@code null} if locking succeeded, or the existing lock if locking failed
401     */
402    Lock setLock(Lock lock);
403
404    /**
405     * Removes a lock from this document.
406     *
407     * @param the owner to check, or {@code null} for no check
408     * @return {@code null} if there was no lock or if removal succeeded, or a lock if it blocks removal due to owner
409     *         mismatch
410     */
411    Lock removeLock(String owner);
412
413    /**
414     * Gets the lock if one set on this document.
415     *
416     * @return the lock, or {@code null} if no lock is set
417     */
418    Lock getLock();
419
420    /**
421     * Gets a child document given its name.
422     * <p>
423     * Throws {@link DocumentNotFoundException} if the document could not be found.
424     *
425     * @param name the name of the child to retrieve
426     * @return the child if exists
427     * @throws DocumentNotFoundException if the child does not exist
428     */
429    Document getChild(String name);
430
431    /**
432     * Gets the children of the document.
433     * <p>
434     * Returns an empty list for non-folder documents.
435     *
436     * @return the children
437     */
438    List<Document> getChildren();
439
440    /**
441     * Gets a list of the children ids.
442     * <p>
443     * Returns an empty list for non-folder documents.
444     *
445     * @return a list of children ids.
446     * @since 1.4.1
447     */
448    List<String> getChildrenIds();
449
450    /**
451     * Checks whether this document has a child of the given name.
452     * <p>
453     * Returns {@code false} for non-folder documents.
454     *
455     * @param name the name of the child to check
456     * @return {@code true} if the child exists, {@code false} otherwise
457     */
458    boolean hasChild(String name);
459
460    /**
461     * Tests if the document has any children.
462     * <p>
463     * Returns {@code false} for non-folder documents.
464     *
465     * @return {@code true} if the document has children, {@code false} otherwise
466     */
467    boolean hasChildren();
468
469    /**
470     * Creates a new child document of the given type.
471     * <p>
472     * Throws an error if this document is not a folder.
473     *
474     * @param name the name of the new child to create
475     * @param typeName the type of the child to create
476     * @return the newly created document
477     */
478    Document addChild(String name, String typeName);
479
480    /**
481     * Orders the given source child before the destination child.
482     * <p>
483     * Both source and destination must be names that point to child documents of this document. The source document
484     * will be placed before the destination one. If destination is {@code null}, the source document will be appended
485     * at the end of the children list.
486     *
487     * @param src the document to move
488     * @param dest the document before which to place the source document
489     */
490    void orderBefore(String src, String dest);
491
492    /**
493     * Creates a new version.
494     *
495     * @param label the version label
496     * @param checkinComment the checkin comment
497     * @return the created version
498     */
499    Document checkIn(String label, String checkinComment);
500
501    void checkOut();
502
503    /**
504     * Gets the list of version ids for this document.
505     *
506     * @return the list of version ids
507     * @since 1.4.1
508     */
509    List<String> getVersionsIds();
510
511    /**
512     * Gets the versions for this document.
513     *
514     * @return the versions of the document, or an empty list if there are no versions
515     */
516    List<Document> getVersions();
517
518    /**
519     * Gets the last version of this document.
520     * <p>
521     * Returns {@code null} if there is no version at all.
522     *
523     * @return the last version, or {@code null} if there is no version
524     */
525    Document getLastVersion();
526
527    /**
528     * Gets the source for this document.
529     * <p>
530     * For a version, it's the working copy.
531     * <p>
532     * For a proxy, it's the version the proxy points to.
533     *
534     * @return the source document
535     */
536    Document getSourceDocument();
537
538    /**
539     * Replaces this document's content with the version specified.
540     *
541     * @param version the version to replace with
542     */
543    void restore(Document version);
544
545    /**
546     * Gets a version of this document, given its label.
547     *
548     * @param label the version label
549     * @return the version
550     */
551    Document getVersion(String label);
552
553    /**
554     * Checks whether this document is a version document.
555     *
556     * @return {@code true} if it's a version, {@code false} otherwise
557     */
558    boolean isVersion();
559
560    /**
561     * Gets the version to which a checked in document is linked.
562     * <p>
563     * Returns {@code null} for a checked out document or a version or a proxy.
564     *
565     * @return the version, or {@code null}
566     */
567    Document getBaseVersion();
568
569    /**
570     * Checks whether this document is checked out.
571     *
572     * @return {@code true} if the document is checked out, or {@code false} otherwise
573     */
574    boolean isCheckedOut();
575
576    /**
577     * Gets the version creation date of this document if it's a version or a proxy.
578     *
579     * @return the version creation date, or {@code null} if it's not a version or a proxy
580     */
581    Calendar getVersionCreationDate();
582
583    /**
584     * Gets the version check in comment of this document if it's a version or a proxy.
585     *
586     * @return the check in comment, or {@code null} if it's not a version or a proxy
587     */
588    String getCheckinComment();
589
590    /**
591     * Gets the version series id.
592     *
593     * @return the version series id
594     */
595    String getVersionSeriesId();
596
597    /**
598     * Gets the version label.
599     *
600     * @return the version label
601     */
602    String getVersionLabel();
603
604    /**
605     * Checks whether this document is the latest version.
606     *
607     * @return {@code true} if this is the latest version, or {@code false} otherwise
608     */
609    boolean isLatestVersion();
610
611    /**
612     * Checks whether this document is a major version.
613     *
614     * @return {@code true} if this is a major version, or {@code false} otherwise
615     */
616    boolean isMajorVersion();
617
618    /**
619     * Checks whether this document is the latest major version.
620     *
621     * @return {@code true} if this is the latest major version, or {@code false} otherwise
622     */
623    boolean isLatestMajorVersion();
624
625    /**
626     * Checks if there is a checked out working copy for the version series of this document.
627     *
628     * @return {@code true} if there is a checked out working copy
629     */
630    boolean isVersionSeriesCheckedOut();
631
632    /**
633     * Gets the working copy for this document.
634     *
635     * @return the working copy
636     */
637    Document getWorkingCopy();
638
639    /**
640     * Gets the document (version or live document) to which this proxy points.
641     */
642    Document getTargetDocument();
643
644    /**
645     * Sets the document (version or live document) to which this proxy points.
646     */
647    void setTargetDocument(Document target);
648
649}