001/*
002 *  Copyright 2025 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.plugins.workspaces.calendars.task;
017
018import java.time.LocalDate;
019import java.time.ZoneId;
020import java.time.ZonedDateTime;
021import java.util.Collection;
022import java.util.List;
023import java.util.Map;
024import java.util.Optional;
025import java.util.Set;
026
027import org.apache.solr.common.SolrInputDocument;
028import org.xml.sax.ContentHandler;
029import org.xml.sax.SAXException;
030
031import org.ametys.cms.data.holder.IndexableDataHolder;
032import org.ametys.cms.data.holder.group.IndexableComposite;
033import org.ametys.cms.data.holder.group.IndexableRepeater;
034import org.ametys.cms.model.CMSDataContext;
035import org.ametys.core.user.UserIdentity;
036import org.ametys.core.util.DateUtils;
037import org.ametys.plugins.messagingconnector.EventRecurrenceTypeEnum;
038import org.ametys.plugins.repository.AmetysObject;
039import org.ametys.plugins.repository.AmetysRepositoryException;
040import org.ametys.plugins.repository.data.external.ExternalizableDataProvider.ExternalizableDataStatus;
041import org.ametys.plugins.repository.data.holder.ModifiableDataHolder;
042import org.ametys.plugins.repository.data.holder.values.SynchronizationContext;
043import org.ametys.plugins.repository.data.repositorydata.RepositoryData;
044import org.ametys.plugins.workspaces.calendars.Calendar;
045import org.ametys.plugins.workspaces.calendars.events.CalendarEvent;
046import org.ametys.plugins.workspaces.calendars.events.CalendarEventOccurrence;
047import org.ametys.plugins.workspaces.tasks.Task;
048import org.ametys.runtime.model.Model;
049import org.ametys.runtime.model.ModelItem;
050import org.ametys.runtime.model.ViewItemAccessor;
051import org.ametys.runtime.model.exception.BadDataPathCardinalityException;
052import org.ametys.runtime.model.exception.BadItemTypeException;
053import org.ametys.runtime.model.exception.UndefinedItemPathException;
054import org.ametys.runtime.model.exception.UnknownTypeException;
055import org.ametys.runtime.model.type.DataContext;
056import org.ametys.runtime.model.type.ModelItemType;
057
058/**
059 * Object for a task calendar event
060 */
061public class TaskCalendarEvent implements CalendarEvent
062{
063    private Calendar _calendar;
064    private Task _task;
065    
066    /**
067     * The constructor
068     * @param calendar the calendar
069     * @param task the task
070     */
071    public TaskCalendarEvent(Calendar calendar, Task task)
072    {
073        _calendar = calendar;
074        _task = task;
075    }
076    
077    /**
078     * Return the task link to the calendar event
079     * @return the task
080     */
081    public Task getTask()
082    {
083        return _task;
084    }
085    
086    public void tag(String tag) throws AmetysRepositoryException
087    {
088        throw new UnsupportedOperationException("Can't call method #tag for a TaskCalendarEvent");
089    }
090
091    public void untag(String tag) throws AmetysRepositoryException
092    {
093        throw new UnsupportedOperationException("Can't call method #untag for a TaskCalendarEvent");
094    }
095
096    public Set<String> getTags() throws AmetysRepositoryException
097    {
098        return _task.getTags();
099    }
100
101    public String getName() throws AmetysRepositoryException
102    {
103        return _task.getName();
104    }
105
106    public String getPath() throws AmetysRepositoryException
107    {
108        return _task.getPath();
109    }
110
111    public String getId() throws AmetysRepositoryException
112    {
113        return _task.getId();
114    }
115
116    public <A extends AmetysObject> A getParent() throws AmetysRepositoryException
117    {
118        return _task.getParent();
119    }
120
121    public String getParentPath() throws AmetysRepositoryException
122    {
123        return _task.getParentPath();
124    }
125
126    public Calendar getCalendar()
127    {
128        return _calendar;
129    }
130    
131    public String getTitle()
132    {
133        return _task.getLabel();
134    }
135
136    public String getDescription()
137    {
138        return _task.getDescription();
139    }
140
141    public String getLocation()
142    {
143        return null;
144    }
145
146    public ZonedDateTime getStartDate()
147    {
148        LocalDate date = _task.getStartDate() != null
149                ? _task.getStartDate()
150                : _task.getDueDate();
151        return DateUtils.asZonedDateTime(date, getZone());
152    }
153
154    public ZonedDateTime getEndDate()
155    {
156        LocalDate date = _task.getDueDate() != null
157                ? _task.getDueDate()
158                : _task.getStartDate();
159        return DateUtils.asZonedDateTime(date, getZone());
160    }
161
162    public ZoneId getZone()
163    {
164        return ZoneId.systemDefault();
165    }
166
167    public Boolean getFullDay()
168    {
169        return true;
170    }
171
172    public UserIdentity getCreator()
173    {
174        return _task.getAuthor();
175    }
176
177    public ZonedDateTime getCreationDate()
178    {
179        return _task.getCreationDate();
180    }
181
182    public UserIdentity getLastContributor()
183    {
184        return _task.getAuthor();
185    }
186
187    public ZonedDateTime getLastModified()
188    {
189        return _task.getLastModified();
190    }
191
192    public EventRecurrenceTypeEnum getRecurrenceType()
193    {
194        return EventRecurrenceTypeEnum.NEVER;
195    }
196
197    public Boolean isRecurrent()
198    {
199        return false;
200    }
201
202    public ZonedDateTime getRepeatUntil()
203    {
204        return null;
205    }
206
207    public List<ZonedDateTime> getExcludedOccurences()
208    {
209        return List.of();
210    }
211
212    public List<CalendarEventOccurrence> getOccurrences(ZonedDateTime startDate, ZonedDateTime endDate)
213    {
214        Optional<CalendarEventOccurrence> optionalEvent = getFirstOccurrence(startDate);
215        return (optionalEvent.isPresent() && optionalEvent.get().getStartDate().isBefore(endDate))
216            ? List.of(optionalEvent.get())
217            : List.of();
218    }
219
220    public Optional<CalendarEventOccurrence> getFirstOccurrence(ZonedDateTime date)
221    {
222        ZonedDateTime eventStartDate = getStartDate();
223        ZonedDateTime eventEndDate = getEndDate();
224        
225        if (getFullDay())
226        {
227            eventEndDate = eventEndDate.plusDays(1);
228        }
229        
230        return (eventEndDate.isAfter(date) || eventEndDate.isEqual(date))
231            ? Optional.of(new CalendarEventOccurrence(this, eventStartDate))
232            : Optional.empty();
233    }
234
235    public Optional<CalendarEventOccurrence> getNextOccurrence(CalendarEventOccurrence occurrence)
236    {
237        return Optional.empty();
238    }
239
240    public UserIdentity getOrganiser()
241    {
242        return _task.getAuthor();
243    }
244
245    public List<String> getResources()
246    {
247        return List.of();
248    }
249
250    public void dataToSAX(ContentHandler contentHandler, String dataPath, DataContext context) throws SAXException, BadItemTypeException, UndefinedItemPathException
251    {
252        _task.dataToSAX(contentHandler, dataPath, context);
253    }
254
255    public Object dataToJSON(String dataPath, DataContext context) throws BadItemTypeException, UndefinedItemPathException
256    {
257        return _task.dataToJSON(dataPath, context);
258    }
259
260    public RepositoryData getRepositoryData()
261    {
262        return _task.getRepositoryData();
263    }
264
265    public List<SolrInputDocument> indexData(SolrInputDocument document, CMSDataContext context) throws BadItemTypeException
266    {
267        return _task.indexData(document, context);
268    }
269
270    public Collection< ? extends Model> getModel()
271    {
272        return _task.getModel();
273    }
274
275    public boolean hasValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
276    {
277        return _task.hasValue(dataPath);
278    }
279
280    public boolean hasLocalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
281    {
282        return _task.hasLocalValue(dataPath);
283    }
284
285    public boolean hasExternalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
286    {
287        return _task.hasExternalValue(dataPath);
288    }
289    
290    public boolean hasValue(String dataPath, String dataTypeId) throws IllegalArgumentException, UnknownTypeException, BadDataPathCardinalityException
291    {
292        return _task.hasValue(dataPath, dataTypeId);
293    }
294
295    public boolean hasValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
296    {
297        return _task.hasValueOrEmpty(dataPath);
298    }
299
300    public boolean hasLocalValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
301    {
302        return _task.hasLocalValueOrEmpty(dataPath);
303    }
304
305    public boolean hasExternalValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
306    {
307        return _task.hasExternalValueOrEmpty(dataPath);
308    }
309
310    public Collection<String> getDataNames()
311    {
312        return _task.getDataNames();
313    }
314    
315    public <T> T getValue(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
316    {
317        return _task.getValue(dataPath);
318    }
319
320    public <T> T getLocalValue(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
321    {
322        return _task.getLocalValue(dataPath);
323    }
324
325    public <T> T getExternalValue(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
326    {
327        return _task.getExternalValue(dataPath);
328    }
329
330    public <T> T getValueOrDefault(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
331    {
332        return _task.getValueOrDefault(dataPath);
333    }
334    
335    public <T> T getValueOrDefault(String dataPath, T defaultValue) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
336    {
337        return _task.getValueOrDefault(dataPath, defaultValue);
338    }
339    
340    public <T> T getValueOfType(String dataPath, String dataTypeId) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
341    {
342        return _task.getValueOfType(dataPath, dataTypeId);
343    }
344    
345    public <T> T getValueOfTypeOrDefault(String dataPath, String dataTypeId, T defaultValue) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
346    {
347        return _task.getValueOfTypeOrDefault(dataPath, dataTypeId, defaultValue);
348    }
349
350    public <T> T getValueWithMultiValuedPathSegments(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
351    {
352        return _task.getValueWithMultiValuedPathSegments(dataPath);
353    }
354
355    public ExternalizableDataStatus getStatus(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
356    {
357        return _task.getStatus(dataPath);
358    }
359    
360    public boolean isMultiple(String dataPath) throws IllegalArgumentException, UndefinedItemPathException
361    {
362        return _task.isMultiple(dataPath);
363    }
364    
365    public boolean isMultiple(String dataPath, String dataTypeId) throws IllegalArgumentException, UndefinedItemPathException
366    {
367        return _task.isMultiple(dataPath, dataTypeId);
368    }
369    
370    public <X extends ModelItemType> X getType(String dataPath) throws IllegalArgumentException, UndefinedItemPathException
371    {
372        return _task.getType(dataPath);
373    }
374    
375    public void copyTo(ModifiableDataHolder dataHolder) throws BadItemTypeException, UndefinedItemPathException
376    {
377        _task.copyTo(dataHolder);
378    }
379    
380    public void copyTo(ModifiableDataHolder dataHolder, DataContext context) throws BadItemTypeException, UndefinedItemPathException
381    {
382        _task.copyTo(dataHolder, context);
383    }
384
385    public void dataToSAX(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor, DataContext context) throws SAXException, BadItemTypeException
386    {
387        _task.dataToSAX(contentHandler, viewItemAccessor, context);
388    }
389
390    public void dataToSAXForEdition(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor, DataContext context) throws SAXException, BadItemTypeException
391    {
392        _task.dataToSAXForEdition(contentHandler, viewItemAccessor, context);
393    }
394
395    public Map<String, Object> dataToJSON(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException
396    {
397        return _task.dataToJSON(viewItemAccessor, context);
398    }
399
400    public Map<String, Object> dataToJSONForEdition(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException
401    {
402        return _task.dataToJSONForEdition(viewItemAccessor, context);
403    }
404
405    public Map<String, Object> dataToMap(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException
406    {
407        return _task.dataToMap(viewItemAccessor, context);
408    }
409
410    public boolean hasDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values) throws BadItemTypeException
411    {
412        return _task.hasDifferences(viewItemAccessor, values);
413    }
414
415    public boolean hasDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values, SynchronizationContext context) throws BadItemTypeException
416    {
417        return _task.hasDifferences(viewItemAccessor, values, context);
418    }
419
420    public Collection<ModelItem> getDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values) throws BadItemTypeException
421    {
422        return _task.getDifferences(viewItemAccessor, values);
423    }
424
425    public Collection<ModelItem> getDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values, SynchronizationContext context) throws BadItemTypeException
426    {
427        return _task.getDifferences(viewItemAccessor, values, context);
428    }
429
430    public IndexableComposite getComposite(String compositePath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
431    {
432        return _task.getComposite(compositePath);
433    }
434
435    public IndexableComposite getLocalComposite(String compositePath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
436    {
437        return _task.getLocalComposite(compositePath);
438    }
439
440    public IndexableComposite getExternalComposite(String compositePath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
441    {
442        return _task.getExternalComposite(compositePath);
443    }
444
445    public IndexableRepeater getRepeater(String repeaterPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
446    {
447        return _task.getRepeater(repeaterPath);
448    }
449
450    public IndexableRepeater getLocalRepeater(String repeaterPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
451    {
452        return _task.getLocalRepeater(repeaterPath);
453    }
454
455    public IndexableRepeater getExternalRepeater(String repeaterPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException
456    {
457        return _task.getExternalRepeater(repeaterPath);
458    }
459
460    public Optional< ? extends IndexableDataHolder> getParentDataHolder()
461    {
462        return _task.getParentDataHolder();
463    }
464
465    public IndexableDataHolder getRootDataHolder()
466    {
467        return _task.getRootDataHolder();
468    }
469}