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.cms.trash.observer;
017
018import java.lang.reflect.ParameterizedType;
019import java.util.Map;
020
021import org.apache.avalon.framework.service.ServiceException;
022import org.apache.avalon.framework.service.ServiceManager;
023import org.apache.avalon.framework.service.Serviceable;
024
025import org.ametys.cms.ObservationConstants;
026import org.ametys.core.observation.Event;
027import org.ametys.core.observation.ObservationManager;
028import org.ametys.core.observation.Observer;
029import org.ametys.plugins.repository.AmetysObject;
030import org.ametys.plugins.repository.AmetysObjectResolver;
031import org.ametys.plugins.repository.trash.TrashableAmetysObject;
032
033/**
034 * Abstract observer to send added notification of each object restored by the trash.
035 * @param <T> The type of the restored object
036 */
037@SuppressWarnings("unchecked")
038public abstract class AbstractAmetysObjectAddedObserver<T extends TrashableAmetysObject> implements Observer, Serviceable
039{
040    private AmetysObjectResolver _resolver;
041    private ObservationManager _observationManager;
042    
043    private Class<T> _type;
044    {
045        // Get the <T> class bu going up in the implementation untill the superclass is this abstract class (AbstractElementType)
046        Class c = this.getClass();
047        while (!c.getSuperclass().equals(AbstractAmetysObjectAddedObserver.class))
048        {
049            c = c.getSuperclass();
050        }
051
052        // The super class is now AbstractElementType, which is Parameterized, so we can get the type arguments
053        _type = (Class<T>) ((ParameterizedType) c.getGenericSuperclass()).getActualTypeArguments()[0];
054    }
055    
056    public void service(ServiceManager manager) throws ServiceException
057    {
058        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
059        _observationManager = (ObservationManager) manager.lookup(ObservationManager.ROLE);
060    }
061
062    public int getPriority()
063    {
064        // Should be launch soon in the process
065        return 500;
066    }
067
068    public boolean supports(Event event)
069    {
070        return event.getId().equals(ObservationConstants.EVENT_TRASH_RESTORED);
071    }
072
073    public void observe(Event event, Map<String, Object> transientVars) throws Exception
074    {
075        T ametysObject = _getAmetysObject(event);
076        if (ametysObject != null)
077        {
078            _observationManager.notify(new Event(getEventId(), event.getIssuer(), getEventParams(ametysObject)));
079        }
080    }
081    
082    /**
083     * Get event identifier to notify.
084     * @return the event id
085     */
086    protected abstract String getEventId();
087    
088    /**
089     * Get the event params to send in the notification.
090     * @param ametysObject The Ametys object on which the event is send
091     * @return the event params as a map
092     */
093    protected abstract Map<String, Object> getEventParams(T ametysObject);
094    
095    /**
096     * Get the Ametys object and type it from the event arguments.
097     * @param event the event
098     * @return the typed Ametys object or null if not found or not of the parameterized type
099     */
100    private T _getAmetysObject(Event event)
101    {
102        String ametysObjectId = (String) event.getArguments().get(ObservationConstants.ARGS_AMETYS_OBJECT_ID);
103        AmetysObject ametysObject = _resolver.resolveById(ametysObjectId);
104        return _type.isInstance(ametysObject) ? _type.cast(ametysObject) : null;
105    }
106}