001/*
002 *  Copyright 2023 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.statistics;
017
018import java.util.ArrayList;
019import java.util.Comparator;
020import java.util.List;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.avalon.framework.service.Serviceable;
025import org.apache.commons.lang3.StringUtils;
026
027import org.ametys.cms.contenttype.ContentType;
028import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
029import org.ametys.cms.repository.Content;
030import org.ametys.cms.repository.ContentQueryHelper;
031import org.ametys.cms.repository.ContentTypeExpression;
032import org.ametys.core.util.I18nUtils;
033import org.ametys.plugins.repository.AmetysObjectIterable;
034import org.ametys.plugins.repository.AmetysObjectResolver;
035import org.ametys.plugins.repository.query.expression.AndExpression;
036import org.ametys.plugins.repository.query.expression.Expression;
037import org.ametys.plugins.repository.query.expression.Expression.Operator;
038import org.ametys.plugins.repository.query.expression.NotExpression;
039import org.ametys.runtime.i18n.I18nizableText;
040import org.ametys.runtime.plugin.component.PluginAware;
041import org.ametys.runtime.plugins.admin.statistics.Statistics;
042import org.ametys.runtime.plugins.admin.statistics.StatisticsNode;
043import org.ametys.runtime.plugins.admin.statistics.StatisticsProvider;
044import org.ametys.runtime.plugins.admin.statistics.StatisticsValue;
045
046/**
047 * CMS statistics
048 */
049public class CMSStatisticsProvider implements StatisticsProvider, Serviceable, PluginAware
050{
051    private String _id;
052    private AmetysObjectResolver _ametysResolver;
053    private ContentTypeExtensionPoint _contentTypeExtensionPoint;
054    private I18nUtils _i18nUtils;
055
056    public void service(ServiceManager manager) throws ServiceException
057    {
058        _ametysResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
059        _contentTypeExtensionPoint = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE);
060        _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
061    }
062    
063    public void setPluginInfo(String pluginName, String featureName, String id)
064    {
065        _id = id;
066    }
067    
068    public Statistics getStatistics()
069    {
070        return new StatisticsNode(
071            _id,
072            new I18nizableText("plugin.cms", "PLUGINS_CMS_STATISTICS_LABEL"),
073            "ametysicon-desktop-archive-black",
074            null,
075            List.of(
076                new StatisticsNode(
077                    "contents",
078                    new I18nizableText("plugin.cms", "PLUGINS_CMS_STATISTICS_CONTENTS_LABEL"),
079                    "ametysicon-text70",
080                    _countAllContents(null),
081                    _getContentTypes(),
082                    false
083                )
084            ),
085            true
086        );
087    }
088    
089    private List<Statistics> _getContentTypes()
090    {
091        List<Statistics> stats = new ArrayList<>();
092        
093        List<Expression> notContentType = new ArrayList<>();
094        
095        for (String contentTypeId : _contentTypeExtensionPoint.getExtensionsIds())
096        {
097            ContentType contentType = _contentTypeExtensionPoint.getExtension(contentTypeId);
098            
099            if (!contentType.isAbstract())
100            {
101                stats.add(new StatisticsValue(
102                    contentTypeId,
103                    new I18nizableText(StringUtils.defaultString(_i18nUtils.translate(contentType.getLabel(), contentType.getId()))), // Translate now for sorting
104                    StringUtils.defaultIfBlank(contentType.getIconGlyph(), "ametysicon-text61"),
105                    _countAllContents(contentTypeId)
106                ));
107                
108                notContentType.add(new NotExpression(new ContentTypeExpression(Operator.EQ, contentTypeId)));
109            }
110        }
111        
112        stats.sort(new Comparator<>() {
113            public int compare(Statistics o1, Statistics o2)
114            {
115                return o1.getLabel().getLabel().compareTo(o2.getLabel().getLabel());
116            }
117        });
118        
119        String query = ContentQueryHelper.getContentXPathQuery(new AndExpression(notContentType.toArray(new NotExpression[notContentType.size()])));
120        try (AmetysObjectIterable<Content> contents = _ametysResolver.query(query))
121        {
122            stats.add(0, new StatisticsValue(
123                "unknown",
124                new I18nizableText("plugin.cms", "PLUGINS_CMS_STATISTICS_CONTENTS_UNKNOWN_LABEL"),
125                "ametysicon-file-extension-generic-unknown",
126                contents.getSize()
127            ));
128        }
129        
130        return stats;
131    }
132
133    private long _countAllContents(String contentTypeId)
134    {
135        String query = ContentQueryHelper.getContentXPathQuery(contentTypeId != null ? new ContentTypeExpression(Operator.EQ, contentTypeId) : null);
136        try (AmetysObjectIterable<Content> contents = _ametysResolver.query(query))
137        {
138            return contents.getSize();
139        }
140    }
141}