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