001/*
002 *  Copyright 2014 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.jcr;
017
018import java.time.ZonedDateTime;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import javax.jcr.Node;
024
025import org.apache.commons.lang.StringUtils;
026
027import org.ametys.cms.data.ametysobject.ModifiableModelAwareDataAwareAmetysObject;
028import org.ametys.cms.data.holder.ModifiableIndexableDataHolder;
029import org.ametys.cms.data.holder.impl.DefaultModifiableModelAwareDataHolder;
030import org.ametys.plugins.explorer.ExplorerNode;
031import org.ametys.plugins.explorer.ModifiableExplorerNode;
032import org.ametys.plugins.repository.AmetysObject;
033import org.ametys.plugins.repository.AmetysObjectIterable;
034import org.ametys.plugins.repository.AmetysRepositoryException;
035import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
036import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
037import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject;
038import org.ametys.plugins.workspaces.calendars.Calendar;
039import org.ametys.plugins.workspaces.calendars.WorkflowAwareCalendar;
040import org.ametys.plugins.workspaces.calendars.events.CalendarEvent;
041import org.ametys.plugins.workspaces.calendars.events.CalendarEventOccurrence;
042import org.ametys.plugins.workspaces.project.objects.Project;
043
044/**
045 * Default implementation of an {@link Calendar}, backed by a JCR node.<br>
046 */
047public class JCRCalendar extends DefaultTraversableAmetysObject<JCRCalendarFactory> implements WorkflowAwareCalendar, ModifiableExplorerNode, ModifiableModelAwareDataAwareAmetysObject
048{
049    /** application id for resources collections. */
050    public static final String APPLICATION_ID = "Ametys.plugins.explorer.applications.Calendar";
051    
052    /** Constants for title Calendar* */
053    public static final String CALENDAR_TITLE = "title";
054    
055    /** Constants for description Calendar* */
056    public static final String CALENDAR_DESC = "description";
057    
058    /** Constants for color Calendar* */
059    public static final String CALENDAR_COLOR = "color";
060    
061    /** Constants for color Visibility* */
062    public static final String CALENDAR_VISIBILITY = "visibility";
063    
064    /** Constants for workflowName Calendar* */
065    public static final String CALENDAR_WORKFLOW_NAME = "workflowName";
066    
067    /** Constants for template description Calendar* */
068    public static final String CALENDAR_TEMPLATE_DESC = "template-description";
069    
070    /** Constants for Calendar ICS token */
071    public static final String CALENDAR_ICS_TOKEN = "ics-token";
072    
073    /**
074     * Creates an {@link JCRCalendar}.
075     * @param node the node backing this {@link AmetysObject}
076     * @param parentPath the parentPath in the Ametys hierarchy
077     * @param factory the DefaultAmetysObjectFactory which created the AmetysObject
078     */
079    public JCRCalendar(Node node, String parentPath, JCRCalendarFactory factory)
080    {
081        super(node, parentPath, factory);
082    }
083
084    public String getIconCls()
085    {
086        return "calendar";
087    }
088
089    public String getApplicationId()
090    {
091        return APPLICATION_ID;
092    }
093
094    public Project getProject()
095    {
096        return _getFactory().getProjectManager().getParentProject(this);
097    }
098    
099    public String getExplorerPath()
100    {
101        AmetysObject parent = getParent();
102        
103        if (parent instanceof ExplorerNode)
104        {
105            return ((ExplorerNode) parent).getExplorerPath() + "/" + getName();
106        }
107        else
108        {
109            return "";
110        }
111    }
112    
113    public String getDescription()
114    {
115        return getValue(CALENDAR_DESC);
116    }
117
118    public String getColor()
119    {
120        return getValue(CALENDAR_COLOR);
121    }
122    
123    public CalendarVisibility getVisibility()
124    {
125        if (hasValue(CALENDAR_VISIBILITY))
126        {
127            return CalendarVisibility.valueOf(getValue(CALENDAR_VISIBILITY));
128        }
129        else
130        {
131            return CalendarVisibility.PRIVATE;
132        }
133    }
134    
135    public String getWorkflowName()
136    {
137        return getValue(CALENDAR_WORKFLOW_NAME);
138    }
139    
140    public String getTemplateDescription()
141    {
142        return getValue(CALENDAR_TEMPLATE_DESC, false, StringUtils.EMPTY);
143    }
144    
145    public List<Calendar> getChildCalendars()
146    {
147        return this.getChildren().stream()
148                .filter(Calendar.class::isInstance)
149                .map(Calendar.class::cast)
150                .toList();
151    }
152    
153    public List<CalendarEvent> getAllEvents()
154    {
155        return this.getChildren().stream()
156                    .filter(CalendarEvent.class::isInstance)
157                    .map(CalendarEvent.class::cast)
158                    .toList();
159    }
160    
161    public Map<CalendarEvent, List<CalendarEventOccurrence>> getEvents(ZonedDateTime startDate, ZonedDateTime endDate)
162    {
163        Map<CalendarEvent, List<CalendarEventOccurrence>> events = new HashMap<>();
164        
165        for (CalendarEvent event : getAllEvents())
166        {
167            List<CalendarEventOccurrence> occurences = event.getOccurrences(startDate, endDate);
168            if (!occurences.isEmpty())
169            {
170                events.put(event, occurences);
171            }
172        }
173        
174        return events;
175    }
176
177    public void setDescription(String desc)
178    {
179        setValue(CALENDAR_DESC, desc);
180    }
181
182    public void setColor(String color)
183    {
184        setValue(CALENDAR_COLOR, color); 
185    }
186    
187    public void setVisibility(CalendarVisibility visibility)
188    {
189        setValue(CALENDAR_VISIBILITY, visibility.name());
190    }
191
192    public void setWorkflowName(String workflowName)
193    {
194        setValue(CALENDAR_WORKFLOW_NAME, workflowName); 
195    }
196    
197    public void setTemplateDescription(String templateDesc)
198    {
199        setValue(CALENDAR_TEMPLATE_DESC, templateDesc);
200    }
201    
202    public boolean hasChildExplorerNodes() throws AmetysRepositoryException
203    {
204        try (AmetysObjectIterable<AmetysObject> children = getChildren())
205        {
206            for (AmetysObject child : children)
207            {
208                if (child instanceof ExplorerNode)
209                {
210                    return true;
211                }
212            }
213    
214            return false;
215        }
216    }
217    
218    public String getIcsUrlToken()
219    {
220        return getValue(CALENDAR_ICS_TOKEN);
221    }
222    
223    public void setIcsUrlToken(String token)
224    {
225        if (token != null)
226        {
227            setValue(CALENDAR_ICS_TOKEN, token);
228        }
229        else
230        {
231            removeValue(CALENDAR_ICS_TOKEN);
232        }
233    }
234
235    public ModifiableIndexableDataHolder getDataHolder()
236    {
237        ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode());
238        return new DefaultModifiableModelAwareDataHolder(repositoryData, _getFactory().getCalendarEventModel());
239    }
240}