001/*
002 *  Copyright 2017 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.odfweb.observation;
017
018import java.util.Map;
019
020import org.apache.avalon.framework.service.ServiceException;
021import org.apache.avalon.framework.service.ServiceManager;
022import org.apache.avalon.framework.service.Serviceable;
023import org.apache.commons.lang3.ArrayUtils;
024
025import org.ametys.cms.ObservationConstants;
026import org.ametys.cms.content.ContentHelper;
027import org.ametys.cms.contenttype.ContentType;
028import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
029import org.ametys.cms.contenttype.ContentTypesHelper;
030import org.ametys.cms.contenttype.MetadataDefinition;
031import org.ametys.cms.contenttype.MetadataType;
032import org.ametys.cms.repository.Content;
033import org.ametys.core.observation.Event;
034import org.ametys.core.observation.Observer;
035import org.ametys.odf.orgunit.OrgUnit;
036import org.ametys.odf.program.AbstractProgram;
037import org.ametys.odf.program.ProgramFactory;
038import org.ametys.odf.tree.OdfClassificationHandler;
039import org.ametys.plugins.odfweb.repository.FirstLevelPageFactory;
040import org.ametys.plugins.odfweb.repository.OdfPageHandler;
041import org.ametys.plugins.repository.AmetysObjectIterable;
042import org.ametys.plugins.repository.AmetysObjectResolver;
043import org.ametys.plugins.repository.query.expression.Expression;
044import org.ametys.plugins.repository.query.expression.VirtualFactoryExpression;
045import org.ametys.runtime.plugin.component.AbstractLogEnabled;
046import org.ametys.web.repository.page.Page;
047import org.ametys.web.repository.page.PageQueryHelper;
048
049/**
050 * This observer clears the cache of enumerated {@link OrgUnit} values or {@link Content}s which are {@link ContentHelper#isReferenceTable(Content) part of reference table} 
051 * when an {@link OrgUnit} or reference table content is added, modified, moved or deleted.
052 */
053public class ClearLevelCacheObserver extends AbstractLogEnabled implements Observer, Serviceable
054{
055    private ContentHelper _contentHelper;
056    private OdfClassificationHandler _odfClassificationHandler;
057    private AmetysObjectResolver _resolver;
058    private OdfPageHandler _odfPageHandler;
059    private ContentTypeExtensionPoint _cTypeEP;
060    private ContentTypesHelper _cTypesHelper;
061    
062    @Override
063    public void service(ServiceManager manager) throws ServiceException
064    {
065        _contentHelper = (ContentHelper) manager.lookup(ContentHelper.ROLE);
066        _odfClassificationHandler = (OdfClassificationHandler) manager.lookup(OdfClassificationHandler.ROLE);
067        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
068        _odfPageHandler = (OdfPageHandler) manager.lookup(OdfPageHandler.ROLE);
069        _cTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE);
070        _cTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE);
071    }
072    
073    @Override
074    public boolean supports(Event event)
075    {
076        String eventId = event.getId();
077        Content content = (Content) event.getArguments().get(ObservationConstants.ARGS_CONTENT);
078        return (eventId.equals(ObservationConstants.EVENT_CONTENT_DELETING)
079                || eventId.equals(ObservationConstants.EVENT_CONTENT_MODIFIED/* handles moved orgUnit too */) 
080                || eventId.equals(ObservationConstants.EVENT_CONTENT_ADDED))
081                && content != null && (content instanceof OrgUnit || _contentHelper.isReferenceTable(content)); 
082    }
083    
084    @Override
085    public int getPriority(Event event)
086    {
087        return MAX_PRIORITY;
088    }
089
090    @Override
091    public void observe(Event event, Map<String, Object> transientVars) throws Exception
092    {
093        Content content = (Content) event.getArguments().get(ObservationConstants.ARGS_CONTENT);
094        if (content instanceof OrgUnit)
095        {
096            _odfClassificationHandler.clearLevelValues(AbstractProgram.ORG_UNITS_REFERENCES, content.getLanguage());
097        }
098        else
099        {
100            // is reference table
101            AmetysObjectIterable<Page> rootPages = _getODFRootPages();
102            if (rootPages.getSize() == 0)
103            {
104                getLogger().debug("There is no ODF root page, nothing to invalidate");
105                return;
106            }
107            
108            String[] simpleContentTypes = content.getTypes();
109            ContentType programCType = _cTypeEP.getExtension(ProgramFactory.PROGRAM_CONTENT_TYPE);
110            
111            for (Page rootPage : rootPages)
112            {
113                String level1Metadata = _odfPageHandler.getLevel1Metadata(rootPage);
114                MetadataDefinition level1MetaDef = _cTypesHelper.getMetadataDefinition(level1Metadata, programCType);
115                String level2Metadata = _odfPageHandler.getLevel2Metadata(rootPage);
116                MetadataDefinition level2MetaDef = _cTypesHelper.getMetadataDefinition(level2Metadata, programCType);
117                if (level1MetaDef.getType() == MetadataType.CONTENT && ArrayUtils.contains(simpleContentTypes, level1MetaDef.getContentType()))
118                {
119                    _odfClassificationHandler.clearLevelValues(level1Metadata, content.getLanguage());
120                }
121                if (level2MetaDef.getType() == MetadataType.CONTENT && ArrayUtils.contains(simpleContentTypes, level2MetaDef.getContentType()))
122                {
123                    _odfClassificationHandler.clearLevelValues(level2Metadata, content.getLanguage());
124                }
125            }
126        }
127    }
128    
129    /**
130     * Get the ODF root pages
131     * @return the ODF root pages
132     */
133    protected AmetysObjectIterable<Page> _getODFRootPages()
134    {
135        Expression expression = new VirtualFactoryExpression(FirstLevelPageFactory.class.getName());
136        String query = PageQueryHelper.getPageXPathQuery(null, null, null, expression, null);
137        
138        return _resolver.query(query);
139    }
140}