001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
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: package org.outerj.daisy.repository;
017:
018: import org.outerx.daisy.x10.DocumentDocument;
019:
020: import java.util.Map;
021: import java.util.Date;
022:
023: /**
024: * A document in the repository. This object actually always represents one
025: * particular variant (branch-language combination) of the document. There
026: * is no separate object representing a document itself as such, access to
027: * documents is always done through a certain variant of it (since access
028: * control is also determined based on the information that is part of the
029: * variant). Letting a document object represent both the document and
030: * document variant was also the most backwards-compatible way to introduce
031: * the variants feature.
032: *
033: * <p>Since one object is used to manipulate both the document and document
034: * variant, most methods include a mentioning of whether they apply to the
035: * document or the document variant. All methods inherited from
036: * {@link VersionedData} are variant-level methods.
037: *
038: * <p>A document can be created using {@link Repository#createDocument(String, String)}
039: * or retrieved using {@link Repository#getDocument(String, boolean)}.
040: *
041: */
042: public interface Document extends VersionedData {
043: /**
044: * Returns the id of this document. For newly created documents, this method
045: * returns null until {@link #save()} is called.
046: */
047: String getId();
048:
049: /**
050: * Returns the sequence ID part of the document ID. This method returns -1
051: * until {@link #save()} is called.
052: *
053: * @since Daisy 2.0
054: */
055: long getSeqId();
056:
057: /**
058: * Returns the sequence ID part of the document ID. This method returns -1
059: * until {@link #save()} is called.
060: *
061: * @since Daisy 2.0
062: */
063: String getNamespace();
064:
065: /**
066: * Returns true if this document has never been saved yet (thus does
067: * not exist in the repository yet).
068: */
069: boolean isNew();
070:
071: long getBranchId();
072:
073: long getLanguageId();
074:
075: /**
076: * @return null for documents which have not yet been saved.
077: */
078: VariantKey getVariantKey();
079:
080: /**
081: * Returns true if the variant represented by this document object has
082: * never been stored yet.
083: */
084: boolean isVariantNew();
085:
086: /**
087: * Requests that this new document will be saved with the given document ID.
088: *
089: * <p>This can only be done for document IDs in a namespace other than
090: * the namespace of the current repository. This is simply because the
091: * current repository is responsible itself for the assigning numbers
092: * to its documents. For foreign namespaces, it is assumed that some
093: * external entity is responsible for the numbering (typically another
094: * Daisy repository, though it could be anything).
095: *
096: * <p>Setting the document ID is only possible for new, not-yet-saved
097: * documents.
098: *
099: * <p>If a document with the given ID would already exist in the
100: * repository, then this will give an exception when saving the document.
101: *
102: * @param documentId allowed to be null, in which case a previous setting is reset
103: *
104: * @since Daisy 2.0
105: *
106: */
107: void setRequestedId(String documentId);
108:
109: String getRequestedId();
110:
111: /**
112: * Returns the available variants for this document. If the document is new and unsaved, this
113: * returns an empty list. If the document variant in this document is new and unsaved, the
114: * returned list will not yet contain this new variant. Thus only variants persisted in the
115: * repository are returned. This method does the same as {@link Repository#getAvailableVariants(String)}.
116: */
117: AvailableVariants getAvailableVariants() throws RepositoryException;
118:
119: /**
120: * Returns the id of the document type to which this document adheres.
121: * Document types themselve are managed via the {@link org.outerj.daisy.repository.schema.RepositorySchema}.
122: *
123: * <p>The document type is a variant-level property.
124: */
125: long getDocumentTypeId();
126:
127: /**
128: * Changes the document type of this document.
129: *
130: * <p>Will throw an exception if the document type does not exist.
131: *
132: * <p>Changing the documenttype does not influence the content of the document,
133: * you have to assure yourself that you update/add/remove parts and fields so
134: * that the document conforms to the document type.
135: *
136: * <p>The document type is a variant-level property.
137: */
138: void changeDocumentType(long documentTypeId)
139: throws RepositoryException;
140:
141: /**
142: * See {@link #changeDocumentType(long)}.
143: */
144: void changeDocumentType(String documentTypeName)
145: throws RepositoryException;
146:
147: /**
148: * Gets the name of this document.
149: *
150: * <p>The document name is a variant-level property.
151: *
152: * <p>This is exactly the same as calling {@link VersionedData#getDocumentName}.
153: */
154: String getName();
155:
156: /**
157: * Sets the name of the document. The document name is not required to be unique,
158: * and is versioned, ie changing the document name and then saving the document
159: * will create a new version.
160: *
161: * <p>The document name is a variant-level property.
162: */
163: void setName(String name);
164:
165: /**
166: * Returns the user id of the owner of this document. The owner is the user that
167: * created the document, unless changed.
168: *
169: * <p>The owner is a document-level property.
170: */
171: long getOwner();
172:
173: /**
174: * Change the owner of this document. Only users acting in the Administrator role,
175: * or the current owner, can change the owner.
176: *
177: * <p>The owner is a document-level property.
178: */
179: void setOwner(long userId);
180:
181: /**
182: * Is this a private document or not. A private document is a document that can
183: * only be accessed by its owner, or users having (and acting) in the role of
184: * Administrator.
185: *
186: * <p>This is a document-level property.
187: */
188: boolean isPrivate();
189:
190: /**
191: * Sets the private flag for this document, see also {@link #isPrivate()}.
192: * New documents are not private by default.
193: *
194: * <p>This is a document-level property.
195: */
196: void setPrivate(boolean _private);
197:
198: /**
199: * Gets the time this document was created.
200: *
201: * <p>This is a document-level property.
202: */
203: Date getCreated();
204:
205: /**
206: * Is this document retired or not. A retired document behaves very much likes
207: * a deleted document. Retired documents don't show up in query results (unless
208: * specifically requested).
209: *
210: * <p>This is a variant-level property.
211: */
212: boolean isRetired();
213:
214: /**
215: * Sets the retired flag for this document, see also {@link #isRetired()}.
216: *
217: * <p>This is a variant-level property.
218: */
219: void setRetired(boolean retired);
220:
221: /**
222: * The time this document was last saved. Returns null for documents that
223: * have never been saved yet.
224: *
225: * <p>This is a document-level property. See also {@link #getVariantLastModified()}.
226: */
227: Date getLastModified();
228:
229: /**
230: * Returns the user id of the last user who saved this document.
231: * Returns -1 for documents that have never been saved yet.
232: *
233: * <p>This is a document-level property. See also {@link #getVariantLastModifier()}.
234: */
235: long getLastModifier();
236:
237: /**
238: * The time the document variant was last saved. Returns null for document variants that
239: * have never been saved yet.
240: *
241: * <p>This is a variant-level property. See also {@link #getLastModified()}.
242: */
243: Date getVariantLastModified();
244:
245: /**
246: * Returns the user id of the last user who saved this document variant.
247: * Returns -1 for document variants that have never been saved yet.
248: *
249: * <p>This is a variant-level property. See also {@link #getLastModifier()}.
250: */
251: long getVariantLastModifier();
252:
253: /**
254: * Returns all versions stored for this document.
255: *
256: * <p>In a typical implementation, the returned Version objects will only contain
257: * basic information about the version (like its id and creation time) which is
258: * needed to show a version list, but the actual version content (fields,
259: * parts, ...) will only be loaded when requested.
260: *
261: * <p>This is a variant-level method.
262: */
263: Versions getVersions() throws RepositoryException;
264:
265: /**
266: * Returns the requested version.
267: *
268: * <p>Note that in contrast with the {@link #getVersions()} method, typical
269: * implementations will usually return a Version object containing all details
270: * about the version.
271: *
272: * <p>This is a variant-level method.
273: */
274: Version getVersion(long id) throws RepositoryException;
275:
276: /**
277: * Returns the id of the last stored version. For new, unsaved documents this
278: * returns -1.
279: *
280: * <p>This is a variant-level property.
281: */
282: long getLastVersionId();
283:
284: /**
285: * Returns the Version object for the last stored version, or null for unsaved
286: * documents.
287: *
288: * <p>This is a variant-level method.
289: */
290: Version getLastVersion() throws RepositoryException;
291:
292: /**
293: * Returns the live version of this document, or null if there is none.
294: * The live version is the most recent version that has the state 'publish'.
295: *
296: * <p>This is a variant-level method.
297: */
298: Version getLiveVersion() throws RepositoryException;
299:
300: /**
301: * Returns the id of the live version, or -1 if there is none.
302: *
303: * <p>This is a variant-level method.
304: */
305: long getLiveVersionId();
306:
307: /**
308: * Returns true if the current user can only access live data of the document.
309: */
310: boolean canReadLiveOnly();
311:
312: /**
313: * Sets the value of a field. The field must be part of the document type
314: * of this document.
315: *
316: * <p>This is a variant-level method.
317: *
318: * <p>See {@link #setDocumentTypeChecksEnabled} to disable checks against the document type.
319: *
320: * @param name name of the field type of the field to set.
321: * @param value the value of the field, the type of the object must be in correspondence with the ValueType of the field type.
322: * For multi-value fields, the value should be an array (i.e. Object[] or a more specifically typed array).
323: * For link field types, the value is a VariantKey object. The branch and language fields of the VariantKey
324: * object can be -1 to indicate they are the same as the containing document (recommended for most uses).
325: * For hierarchical fields, the value is a HierarchyPath containing values according to the field type.
326: * For multi-value hierarchical fields, the value is an array of HierarchyPath objects.
327: */
328: void setField(String name, Object value)
329: throws DocumentTypeInconsistencyException;
330:
331: /**
332: * Same as {@link #setField(String, Object)} but using the id of the field type.
333: *
334: * <p>This is a variant-level method.
335: */
336: void setField(long fieldTypeId, Object value)
337: throws DocumentTypeInconsistencyException;
338:
339: /**
340: * Removes the specified field. Silently ignored if the document doesn't have that field.
341: *
342: * <p>This is a variant-level method.
343: *
344: * @param name name of the field type
345: */
346: void deleteField(String name);
347:
348: /**
349: * Removes the specified field. Silently ignored if the document doesn't have that field.
350: *
351: * <p>This is a variant-level method.
352: */
353: void deleteField(long fieldTypeId);
354:
355: /**
356: * Saves a document.
357: *
358: * <p>This is the same as calling {@link #save(boolean)} with argument true.
359: */
360: void save() throws RepositoryException;
361:
362: /**
363: * Saves the document and document variant.
364: *
365: * <p>If only changes have been done to document-level properties,
366: * only the document will be saved. If only changes have been done
367: * to variant-level properties, only the variant will be saved.
368: *
369: * <p>If this is a new document, it will cause an id to be assigned
370: * to this document object.
371: *
372: * <p>Saving the document variant might or might not cause the creation of a new
373: * version, depending on whether any versioned data has changed. Versioned
374: * data includes the parts, fields, links and the document's name. So if
375: * for example only the retired flag changed, customfields were changed,
376: * or collection membership changed, no new version will be created.
377: * After saving, you can get the new version id from the method
378: * {@link #getLastVersionId()}. The state of the new version can be
379: * influenced by using {@link #setNewVersionState(org.outerj.daisy.repository.VersionState)}
380: * before calling save().
381: *
382: *
383: * <p>If someone else holds a pessimistic lock on the document variant, saving it
384: * will fail. Likewise, if another person saved the document since you retrieved
385: * this document object (ie a concurrent modification), saving will also fail.
386: * Note that locks apply only to document variants, so don't protect from concurrent
387: * changes to document-level properties.
388: *
389: * <p>Saving a document will cause the server to send out an assynchronous
390: * event, to which other processes can listen, for example the full
391: * text indexer. (There are separate events for updates to the document and
392: * the variant)
393: *
394: * <p>Using the argument <tt>validate</tt> you can specify whether the document variant
395: * should be validated against its document type. Usually you will always
396: * provide true here. As an example use case for not using validation,
397: * it might be that you just want to mark a
398: * document as retired without bothering that its content doesn't correspond
399: * to the schema anymore.
400: *
401: * @throws DocumentTypeInconsistencyException in case validation against the schema fails.
402: */
403: void save(boolean validate) throws RepositoryException;
404:
405: /**
406: * Validates that this document confirms to its document type.
407: */
408: void validate() throws DocumentTypeInconsistencyException;
409:
410: /**
411: * Sets the VersionState that should be used if a new version is created
412: * when saving the document.
413: *
414: * <p>By default this is VersionState.PUBLISH.
415: */
416: void setNewVersionState(VersionState versionState);
417:
418: /**
419: * See {@link #setNewVersionState(VersionState)}.
420: */
421: VersionState getNewVersionState();
422:
423: /**
424: * Takes a lock on the document variant. If the lock type is "pessimistic", this will prevent
425: * others from saving the document variant while you're working on it. If the lock
426: * is "warn", the lock only serves for informational purposes and will
427: * not enforce anything. So called "optimistic locking" (ie checking against
428: * concurrent modifications) happens always, and doesn't require to take a lock.
429: *
430: * <p>Changing a lock doesn't need a {@link #save()} call afterwards,
431: * calling this method has immediate effect.
432: *
433: * <p>The lock can be removed with {@link #releaseLock()}.
434: *
435: * <p>This is a variant-level method.
436: *
437: * @param duration indication of how long the lock should remain (in ms).
438: * Use -1 for a never-expiring lock.
439: * @return false if someone else already has a lock on this document, in
440: * which case you can call {@link #getLockInfo(boolean)} with false
441: * as parameter to know who is holding the lock.
442: */
443: boolean lock(long duration, LockType lockType)
444: throws RepositoryException;
445:
446: /**
447: * Releases the lock on the document variant. This can only be done by the person
448: * holding this lock, or by an Administrator.
449: *
450: * <p>This is a variant-level method.
451: *
452: * @return true if the lock is removed (or if there was no lock). If a lock
453: * remains on the document, false will be returned, in which case
454: * you can call {@link #getLockInfo(boolean)} with false
455: * as parameter to know who is holding the lock.
456: */
457: boolean releaseLock() throws RepositoryException;
458:
459: /**
460: * Returns information about the current lock on the document variant.
461: *
462: * <p>This is a variant-level method.
463: *
464: * @param fresh if true, the lock information will be refetched. Otherwise
465: * the existing information stored in this Document object will
466: * be returned (which may be out of date).
467: */
468: LockInfo getLockInfo(boolean fresh) throws RepositoryException;
469:
470: /**
471: * Sets a custom field. A custom field is an arbitrary name/value pair.
472: * Custom fields are not versioned.
473: *
474: * <p>This is a variant-level method.
475: */
476: void setCustomField(String name, String value);
477:
478: /**
479: * Removes the specified custom field. Passes silently if there is no
480: * custom field with the given name.
481: *
482: * <p>This is a variant-level method.
483: */
484: void deleteCustomField(String name);
485:
486: /**
487: * Gets the value of the specified custom field, or null if there is no
488: * custom field with that name.
489: *
490: * <p>This is a variant-level method.
491: */
492: String getCustomField(String name);
493:
494: /**
495: * Returns true if there is a custom field with the specified name.
496: *
497: * <p>This is a variant-level method.
498: */
499: boolean hasCustomField(String name);
500:
501: /**
502: * Removes all custom fields.
503: *
504: * <p>This is a variant-level method.
505: */
506: void clearCustomFields();
507:
508: /**
509: * Returns a map containing the fields, with the field type name being the key.
510: * Making changes to this map will not be reflected in the document.
511: *
512: * <p>This is a variant-level method.
513: */
514: Map<String, String> getCustomFields();
515:
516: /**
517: * Sets a part.
518: *
519: * <p>This is a variant-level method.
520: */
521: void setPart(String partTypeName, String mimeType, byte[] data)
522: throws DocumentTypeInconsistencyException;
523:
524: /**
525: * Sets a part.
526: *
527: * <p>This is a variant-level method.
528: */
529: void setPart(long partTypeId, String mimeType, byte[] data)
530: throws DocumentTypeInconsistencyException;
531:
532: /**
533: * Sets a part.
534: *
535: * <p>This is a variant-level method.
536: */
537: void setPart(String partTypeName, String mimeType,
538: PartDataSource partDataSource)
539: throws DocumentTypeInconsistencyException;
540:
541: /**
542: * Sets a part.
543: *
544: * <p>This is a variant-level method.
545: */
546: void setPart(long partTypeId, String mimeType,
547: PartDataSource partDataSource)
548: throws DocumentTypeInconsistencyException;
549:
550: /**
551: * Update the file name of an already existing part. Throws an exception if the document doesn't
552: * have the indicated part.
553: *
554: * <p>This is a variant-level method.
555: *
556: * @param fileName allowed to be null (to remove the filename information)
557: */
558: void setPartFileName(String partTypeName, String fileName);
559:
560: /**
561: * Update the file name of an already existing part. Throws an exception if the document doesn't
562: * have the indicated part.
563: *
564: * <p>This is a variant-level method.
565: *
566: * @param fileName allowed to be null (to remove the filename information)
567: */
568: void setPartFileName(long partTypeId, String fileName);
569:
570: /**
571: * Update the mime-type of an already existing part. Throws an exception if the document doesn't
572: * have the indicated part.
573: *
574: * <p>This is a variant-level method.
575: */
576: void setPartMimeType(String partTypeName, String mimeType);
577:
578: /**
579: * Update the mime-type of an already existing part. Throws an exception if the document doesn't
580: * have the indicated part.
581: *
582: * <p>This is a variant-level method.
583: */
584: void setPartMimeType(long partTypeId, String mimeType);
585:
586: /**
587: * Removes a part, passes silently if there is no part in the document with the given id.
588: *
589: * <p>This is a variant-level method.
590: */
591: void deletePart(long partTypeId);
592:
593: /**
594: * Removes a part, passes silently if there is no part in the document with the given name.
595: *
596: * <p>This is a variant-level method.
597: */
598: void deletePart(String name);
599:
600: /**
601: * Adds an out-of-line link (at the end of the list).
602: *
603: * <p>This is a variant-level method.
604: */
605: void addLink(String title, String target);
606:
607: /**
608: * Removes an out-of-line link.
609: *
610: * <p>This is a variant-level method.
611: */
612: void deleteLink(int index);
613:
614: /**
615: * Removes all out-of-line links.
616: *
617: * <p>This is a variant-level method.
618: */
619: void clearLinks();
620:
621: /**
622: * Adds the document variant to a supplied Collection.
623: *
624: * @param collection the collection to add the current document to
625: */
626: void addToCollection(DocumentCollection collection);
627:
628: /**
629: * Removes the document variant from a collection
630: *
631: * @param collection the collection from which the document needs to be removed
632: */
633: void removeFromCollection(DocumentCollection collection);
634:
635: /**
636: * Returns the collections the document variant belongs to, null if the document variant
637: * belongs to no Collections.
638: */
639: DocumentCollections getCollections();
640:
641: /**
642: * Checks if the document variant belongs to the specified collection.
643: */
644: boolean inCollection(DocumentCollection collection);
645:
646: /**
647: * Checks if the document variant belongs to the specified collection.
648: */
649: boolean inCollection(long collectionId);
650:
651: DocumentDocument getXml() throws RepositoryException;
652:
653: DocumentDocument getXmlWithoutVariant() throws RepositoryException;
654:
655: DocumentDocument getXmlWithoutVersionedData()
656: throws RepositoryException;
657:
658: /**
659: * Gets the XML of the document but include the data from the
660: * specified version, instead of the current data. This only
661: * applies to the data of the document that is actually versionable, of course.
662: * For the rest of the data, you'll get what's currently in the document
663: * object, whether that data has already been saved or not.
664: */
665: DocumentDocument getXml(long versionId) throws RepositoryException;
666:
667: /**
668: * Removes the document variant from all the collections it belongs to.
669: */
670: void clearCollections();
671:
672: /**
673: * Returns a summary text for the document variant. The summary is only created/updated
674: * when the document is saved. Returns an empty string if there's no summary.
675: * The summary always corresponds to the live version of the document.
676: */
677: String getSummary();
678:
679: /**
680: * If the variant currently loaded in this document object is created from an existing
681: * branch, this method will return the id of that branch, otherwise it will return -1.
682: * Note that the branch could possibly no longer exist.
683: */
684: long getVariantCreatedFromBranchId();
685:
686: /**
687: * Similar to {@link #getVariantCreatedFromBranchId()}.
688: */
689: long getVariantCreatedFromLanguageId();
690:
691: /**
692: * Similar to {@link #getVariantCreatedFromBranchId()}.
693: */
694: long getVariantCreatedFromVersionId();
695:
696: /**
697: * Allows to disable some document type related checks. When disabled,
698: * it is possible to set fields and parts on this document that are
699: * not allowed by the document type. For parts, the mime-type
700: * checking won't be performed either.
701: */
702: void setDocumentTypeChecksEnabled(boolean documentTypeChecksEnabled);
703:
704: long getUpdateCount();
705:
706: long getVariantUpdateCount();
707:
708: /**
709: * The current reference language for this document.
710: * Returns -1 if the reference language is not set.
711: *
712: * <p>Setting the reference language is also used as an indication that the document should be considered to be under "translation management".
713: *
714: * <p>this is a document level method</p>
715: */
716: long getReferenceLanguageId();
717:
718: void setReferenceLanguageId(long referenceLanguageId);
719:
720: void setReferenceLanguage(String referenceLanguageName)
721: throws RepositoryException;
722:
723: /**
724: * Gets the last version for which the change type was major.
725: *
726: * <p>Returns -1 if there is no such version.
727: *
728: * <p>This is an automatically calculated field. This information is fetched
729: * when this document object is retrieved and is not updated afterwards.
730: *
731: * <p>This is a variant level method.
732: */
733: long getLastMajorChangeVersionId();
734:
735: /**
736: * Gets the last version, up to the current live version, for which the change type was major.
737: *
738: * <p>Returns -1 if there is no such version.
739: *
740: * <p>This is an automatically calculated field. This information is fetched
741: * when this document object is retrieved and is not updated afterwards.
742: *
743: * <p>This is a variant level method.
744: */
745: long getLiveMajorChangeVersionId();
746:
747: /**
748: * @return <languageId>:<versionId> to indicate which variant/version the document was synced with
749: * or null if the document is not synced
750: */
751: VersionKey getNewSyncedWith();
752:
753: /**
754: * Sets the 'synced with' value that should be used if a new version is created
755: * as part of saving this document.
756: *
757: * <p>The 'synced with' indicates the version is synced with another language:version.
758: *
759: * <p>Use setSyncedWithVersion(-1,-1) to clear any previous set value.
760: */
761: void setNewSyncedWith(long languageId, long versionId)
762: throws RepositoryException;
763:
764: /**
765: * Alternative to {@link #setNewSyncedWith(long, long)}.
766: *
767: * <p>Use setSyncedWith(null, -1) to indicate the document is not synced anymore.
768: */
769: void setNewSyncedWith(String languageName, long versionId)
770: throws RepositoryException;
771:
772: /**
773: * Sets the 'synced with' pointer by specifying a VersionKey object.
774: * Only the language ID and version ID fields of the VersionKey object
775: * are significant. The syncedWith argument can be null.
776: *
777: * <p>See also {@link #setNewSyncedWith(long, long)}.
778: */
779: void setNewSyncedWith(VersionKey syncedWith)
780: throws RepositoryException;
781:
782: /**
783: * Sets the ChangeType that should be used if a new version is created
784: * when saving the document.
785: *
786: * <p>By default this is ChangeType.MAJOR
787: */
788: void setNewChangeType(ChangeType changeType);
789:
790: ChangeType getNewChangeType();
791:
792: /**
793: * Sets the change comment that should be used if a new version is created
794: * when saving the document.
795: *
796: * <p>By default this is null
797: */
798: void setNewChangeComment(String changeComment);
799:
800: String getNewChangeComment();
801: }
|