001/*
002 *  Copyright 2022 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.repository.activities;
017
018import java.time.ZonedDateTime;
019import java.util.HashMap;
020import java.util.Map;
021
022import javax.jcr.RepositoryException;
023
024import org.ametys.core.observation.Event;
025import org.ametys.core.user.UserIdentity;
026import org.ametys.plugins.repository.AmetysObjectIterable;
027import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
028import org.ametys.plugins.repository.ObservationConstants;
029import org.ametys.runtime.model.type.ModelItemTypeConstants;
030
031/**
032 * Default implementation for an {@link ActivityHolder}
033 * This implementation is backed by a {@link ModifiableTraversableAmetysObject}
034 */
035public class DefaultActivityHolder implements ActivityHolder
036{
037    private ModifiableTraversableAmetysObject _rootCollection;
038    private DefaultActivityHolderFactory _activityHolderFactory;
039
040    /**
041     * Create a default {@link ActivityHolder}
042     * @param rootCollection the ametys object backing this activity holder
043     * @param factory the {@link DefaultActivityHolderFactory} which creates the AmetysObject
044     */
045    public DefaultActivityHolder(ModifiableTraversableAmetysObject rootCollection, DefaultActivityHolderFactory factory)
046    {
047        _rootCollection = rootCollection;
048        _activityHolderFactory = factory;
049    }
050
051    /**
052     * Returns the activity nodes
053     * @return The activities
054     * @throws RepositoryException if failed to get activity nodes
055     */
056    public AmetysObjectIterable<Activity> getActivities() throws RepositoryException
057    {
058        return _rootCollection.getChildren();
059    }
060    
061    public Activity addActivity(ActivityType type, Map<String, Object> parameters, String eventId) throws RepositoryException
062    {
063        return addActivity(ZonedDateTime.now(), type, parameters, _activityHolderFactory.getCurrentUser(), eventId);
064    }
065    
066    /**
067     * Add an activity to the activity holder
068     * @param date the date
069     * @param type the type
070     * @param parameters the parameters
071     * @param author the author
072     * @param eventId the id of the event
073     * @return the activity
074     * @throws RepositoryException when an error occurred
075     */
076    public Activity addActivity(ZonedDateTime date, ActivityType type, Map<String, Object> parameters, UserIdentity author, String eventId) throws RepositoryException
077    {
078        String activityName = ACTIVITY_NAME_PREFIX + date.format(JCR_UTC_FORMAT);
079        
080        Activity activity = _rootCollection.createChild(activityName, ActivityFactory.NODE_TYPE);
081        
082        // Type
083        activity.setValue(ActivityFactory.ACTIVITY_TYPE_ID, type.getId(), ModelItemTypeConstants.STRING_TYPE_ID);
084        
085        // Date
086        activity.setValue(ActivityFactory.DATE, date, ModelItemTypeConstants.DATETIME_TYPE_ID);
087        
088        // Type
089        activity.setValue(ActivityFactory.TYPE, eventId, ModelItemTypeConstants.STRING_TYPE_ID);
090        
091        // Author
092        // TODO GG we should use a constant here
093        activity.setValue(ActivityFactory.AUTHOR, author, "user");
094        
095        type.setAdditionalActivityData(activity, parameters);
096        _rootCollection.saveChanges();
097        
098        _notifyObserver(activity);
099        
100        return activity;
101    }
102    
103    private void _notifyObserver(Activity activity)
104    {
105        Map<String, Object> params = new HashMap<>();
106        // Provide the activity and the id for both sync and async observer
107        params.put(ObservationConstants.ARGS_ACTIVITY, activity);
108        params.put(ObservationConstants.ARGS_ACTIVITY_ID, activity.getId());
109        Event event = new Event(ObservationConstants.EVENT_ACTIVITY_CREATED, activity.getAuthor(), params);
110        _activityHolderFactory.getObservationManager().notify(event);
111    }
112}