001/*
002 *  Copyright 2010 Anyware Services
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 */
016package org.ametys.cms.repository;
017
018import java.time.ZonedDateTime;
019import java.util.Collection;
020import java.util.Locale;
021import java.util.Map;
022import java.util.Optional;
023
024import org.xml.sax.ContentHandler;
025import org.xml.sax.SAXException;
026
027import org.ametys.cms.content.references.OutgoingReferences;
028import org.ametys.cms.data.ametysobject.IndexableAmetysObject;
029import org.ametys.core.user.UserIdentity;
030import org.ametys.plugins.explorer.resources.ResourceCollection;
031import org.ametys.plugins.repository.AmetysRepositoryException;
032import org.ametys.plugins.repository.ModifiableACLAmetysObject;
033import org.ametys.plugins.repository.data.UnknownDataException;
034import org.ametys.plugins.repository.data.holder.DataHolder;
035import org.ametys.plugins.repository.data.holder.ModifiableDataHolder;
036import org.ametys.plugins.repository.dublincore.DublinCoreAwareAmetysObject;
037import org.ametys.plugins.repository.metadata.MetadataAwareAmetysObject;
038import org.ametys.plugins.repository.tag.TagAwareAmetysObject;
039import org.ametys.runtime.model.View;
040
041/**
042 * Content abstraction defined by the following properties:
043 * <dl>
044 *   <dt>type
045 *   <dd>the content type (can only be set on creation)
046 *   <dt>language
047 *   <dd>the language (can only be set on creation)
048 *   <dt>title
049 *   <dd>the title
050 *   <dt>creator
051 *   <dd>the login of the creator
052 *   <dt>creationDate
053 *   <dd>the date when the content was created
054 *   <dt>lastContributor
055 *   <dd>the login of the last contributor
056 *   <dt>lastModified
057 *   <dd>the date when the last modification takes place
058 * </dl>
059 */
060public interface Content extends IndexableAmetysObject, MetadataAwareAmetysObject, DublinCoreAwareAmetysObject, TagAwareAmetysObject, ModifiableACLAmetysObject
061{
062    /** Constants for title attribute */
063    public static final String ATTRIBUTE_TITLE = "title";
064    
065    /**
066     * Record to get referencing contents with additional informations, we can get a limited number of referencing contents, then we would
067     * need the total number of refencing contents and if all references has been resolved.
068     * One referencing content can have several references.
069     * 
070     * @param total The total number of references
071     * @param referencingContents The resolved referencing contents (can be limited)
072     * @param hasOtherReferences <code>true</code> if all references has not been resolved in referencingContents attribute.
073     */
074    public record ReferencingContentsSearch(long total, Collection<Content> referencingContents, boolean hasOtherReferences) { /* empty */ }
075    
076    /**
077     * Retrieves the type identifiers of this content.
078     * @return the type identifiers of this content.
079     */
080    public String[] getTypes();
081    
082    /**
083     * Set the type of this content
084     * @param type the type to set
085     */
086    public void setType(String type);
087    
088    /**
089     * Set the types of this Content.<br>
090     * @param types the types of this content.
091     */
092    public void setTypes(String[] types);
093    
094    /**
095     * Retrieves the mixin type identifiers of this content.
096     * @return the mixin type identifiers of this content.
097     */
098    public String[] getMixinTypes();
099    
100    /**
101     * Set the mixins of this Content.<br>
102     * @param mixins the mixins of this content.
103     */
104    public void setMixinTypes(String[] mixins);
105    
106    /**
107     * Retrieves the language of this content.<br>
108     * @return the language of this content or <code>null</code> if the content is a multilingual content
109     */
110    public String getLanguage();
111
112    /**
113     * Set the type of this Content.<br>
114     * This method may only be called on a new Content, ie. before its first save.
115     * @param language the language of this content.
116     */
117    public void setLanguage(String language);
118    
119    /**
120     * Retrieves the title for the given locale. If the locale is null or does not exist, the first locale will be used.
121     * @param locale The locale. Can be null if the content is not a multilingual content or to get the title in the default locale.
122     * @return the title.
123     * @throws UnknownDataException if this property does not exist.
124     */
125    public String getTitle(Locale locale) throws UnknownDataException;
126    
127    /**
128     * Retrieves the title.
129     * This method is same as {@link #getTitle(Locale)} with a null locale.
130     * Use this method only if you are manipulating no-multilingual content. If not sure, use {@link #getTitle(Locale)} instead.
131     * @return the title.
132     * @throws UnknownDataException if this property does not exist.
133     */
134    public String getTitle() throws UnknownDataException;
135
136    /**
137     * Retrieves the login of the creator.
138     * @return the login of the creator.
139     * @throws UnknownDataException if this property does not exist.
140     * @throws AmetysRepositoryException if an error occurs.
141     */
142    public UserIdentity getCreator() throws UnknownDataException;
143    
144    /**
145     * Retrieves the creation date.
146     * @return the creation date.
147     * @throws UnknownDataException if this property does not exist.
148     * @throws AmetysRepositoryException if an error occurs.
149     */
150    public ZonedDateTime getCreationDate() throws UnknownDataException;
151    
152    /**
153     * Retrieves the login of the last contributor.
154     * @return the login of the last contributor.
155     * @throws UnknownDataException if this property does not exist.
156     * @throws AmetysRepositoryException if an error occurs.
157     */
158    public UserIdentity getLastContributor() throws UnknownDataException;
159    
160    /**
161     * Retrieves the last modification date.
162     * @return the last modification date.
163     * @throws UnknownDataException if this property does not exist.
164     * @throws AmetysRepositoryException if an error occurs.
165     */
166    public ZonedDateTime getLastModified() throws UnknownDataException;
167
168    /**
169     * Retrieves the identity of the first validator
170     * An empty value should not be considered as a content never being validated.
171     * Old content could have been validated before the introduction of this value and have not be updated.
172     * {@link #getFirstValidationDate()} is more reliable for this usage.
173     * 
174     * @return the first validator
175     * @throws AmetysRepositoryException if an error occurs.
176     */
177    public Optional<UserIdentity> getFirstValidator();
178    
179    /**
180     * Retrieves the first validation date
181     * @return the first validation date
182     * @throws UnknownDataException if this property does not exist.
183     * @throws AmetysRepositoryException if an error occurs.
184     */
185    public ZonedDateTime getFirstValidationDate();
186    
187    /**
188     * Retrieves the identity of the last validator.
189     * An empty value should not be considered as a content never being validated.
190     * Old content could have been validated before the introduction of this value and have not be updated.
191     * {@link #getLastValidationDate()} is more reliable for this usage.
192     * 
193     * @return the last validator if the value exists
194     * @throws AmetysRepositoryException if an error occurs.
195     */
196    public Optional<UserIdentity> getLastValidator();
197    
198    /**
199     * Retrieves the last validation date
200     * @return the last validation date
201     * @throws UnknownDataException if this property does not exist.
202     * @throws AmetysRepositoryException if an error occurs.
203     */
204    public ZonedDateTime getLastValidationDate();
205    
206    /**
207     * Retrieves the identity of the last major validator
208     * An empty value should not be considered as a content never being validated.
209     * Old content could have been validated before the introduction of this value and have not be updated.
210     * {@link #getLastMajorValidationDate()} is more reliable for this usage.
211     * 
212     * @return the last major validator
213     * @throws AmetysRepositoryException if an error occurs.
214     */
215    public Optional<UserIdentity> getLastMajorValidator();
216    
217    /**
218     * Retrieves the last validation date resulting from a major modification. At least this is the first validation date
219     * @return the last validation date resulting from a major modification
220     * @throws UnknownDataException if this property does not exist.
221     * @throws AmetysRepositoryException if an error occurs.
222     */
223    public ZonedDateTime getLastMajorValidationDate ();
224    
225    /**
226     * Returns all Contents referencing this Content (as a metadata).
227     * @return all Contents referencing this Content.
228     * @throws AmetysRepositoryException if an error occurs.
229     */
230    public Collection<Content> getReferencingContents() throws AmetysRepositoryException;
231    
232    /**
233     * Returns an object for a limited search of referencing contents with the total of referencing contents, a collection of referencing contents limited to the given limit, and a boolean indicates if there are other references.
234     * @param limit The limit for resolved contents
235     * @return a record with total number of contents, resolved contents and a boolean indicates if there are more references.
236     * @throws AmetysRepositoryException if an error occurs
237     */
238    public ReferencingContentsSearch searchReferencingContents(int limit) throws AmetysRepositoryException;
239    
240    /**
241     * Returns <code>true</code> if there is at least one Content referencing this Content (as a metadata).
242     * @return <code>true</code> if there is at least one Content referencing this Content.
243     * @throws AmetysRepositoryException if an error occurs.
244     */
245    public boolean hasReferencingContents() throws AmetysRepositoryException;
246    
247    /**
248     * Get the stored outgoing references of the content. This references can be used for different purposes, such as testing link consistency for example.
249     * @return A non null map of outgoing references grouped by metadata (key are metadata path)
250     * @throws AmetysRepositoryException if an error occurs.
251     */
252    public Map<String, OutgoingReferences> getOutgoingReferences() throws AmetysRepositoryException;
253
254    /**
255     * Retrieves the attachments root node
256     * @return The attachments root node, or null if the content is working on
257     * an (unmodifiable) old version and the attachments root is missing.
258     * @throws AmetysRepositoryException if an error occurs.
259     */
260    public ResourceCollection getRootAttachments() throws AmetysRepositoryException;
261    
262    /**
263     * Generates SAX events representing this Content.
264     * @param contentHandler the {@link ContentHandler} that will receive the SAX events.
265     * @param locale the {@link Locale} to use for eg. multilingual attributes.
266     * @param view the associated View, or null to generate SAX events for all attributes from the model.
267     * @param saxWorkflowStep if true, also generates SAX events for the current workflow step.
268     * @throws SAXException if an error occurs during the SAX events generation.
269     */
270    public void toSAX(ContentHandler contentHandler, Locale locale, View view, boolean saxWorkflowStep) throws SAXException;
271    
272    /**
273     * Returns the {@link DataHolder} for internal data of this {@link Content}.
274     * @return the {@link DataHolder} for internal data of this {@link Content}
275     */
276    public ModifiableDataHolder getInternalDataHolder();
277}