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