001/*
002 *  Copyright 2021 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.web.duplicate;
017
018import java.util.List;
019import java.util.Map;
020import java.util.Optional;
021import java.util.function.Function;
022import java.util.function.Predicate;
023import java.util.stream.Collectors;
024
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027
028import org.ametys.cms.content.ContentHelper;
029import org.ametys.cms.duplicate.contents.DuplicateContentsManager;
030import org.ametys.cms.duplicate.contents.DuplicateContentsManager.Status;
031import org.ametys.cms.repository.Content;
032import org.ametys.core.schedule.Schedulable;
033import org.ametys.plugins.repository.AmetysObjectIterable;
034import org.ametys.runtime.i18n.I18nizableText;
035import org.ametys.web.content.sitegetter.SiteGetterExtensionPoint;
036import org.ametys.web.repository.content.WebContent;
037import org.ametys.web.repository.site.Site;
038import org.ametys.web.repository.site.SiteManager;
039
040/**
041 * A {@link Schedulable} job for detecting duplicates, overriding {@link org.ametys.cms.duplicate.contents.DuplicateContentsDetectionSchedulable} to get the site to use for links.
042 */
043public class DuplicateContentsDetectionSchedulable extends org.ametys.cms.duplicate.contents.DuplicateContentsDetectionSchedulable
044{
045    /** The extension point for site getters */
046    protected SiteGetterExtensionPoint _siteGetterExtensionPoint;
047
048    /** The site manager. */
049    protected SiteManager _siteManager;
050    
051    @Override
052    public void service(ServiceManager manager) throws ServiceException
053    {
054        super.service(manager);
055        _contentHelper = (ContentHelper) manager.lookup(ContentHelper.ROLE);
056        _siteGetterExtensionPoint = (SiteGetterExtensionPoint) manager.lookup(SiteGetterExtensionPoint.ROLE);
057        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
058    }
059    
060    /**
061     * Render the cms tool link
062     * @param content The content
063     * @return the link
064     */
065    @Override
066    protected String _renderCmsToolLink(Content content)
067    {
068        StringBuilder url = new StringBuilder();
069
070        Optional<Site> site = _siteGetterExtensionPoint.getSiteByContent(content);
071     
072        if (site.isPresent())
073        {
074            String contentBOUrl = _contentHelper.getContentBOUrl(content, Map.of("siteName", site.get().getName()));
075            url.append("<a href=\"");
076            url.append(contentBOUrl);
077            url.append("\">");
078            url.append(content.getTitle());
079            url.append("</a>");
080        }
081        else
082        {
083            url.append(content.getTitle());
084        }
085        return url.toString();
086    }
087    
088    @Override
089    protected String _displayContents(Map<Content, List<Content>> duplicatesMap, Map<Content, List<Content>> nearDuplicatesMap,
090            Map<Content, DuplicateContentsManager.Status> tooComplexMap)
091    {
092
093        AmetysObjectIterable<Site> sites = _siteManager.getSites();
094        StringBuilder body = new StringBuilder();
095        body.append("<ul>");
096        for (Site site : sites)
097        {
098            Map<Content, List<Content>> filteredDuplicatesMap = duplicatesMap.keySet()
099                    .stream()
100                    .filter(WebContent.class::isInstance)
101                    .map(WebContent.class::cast)
102                    .filter(content -> site.equals(content.getSite()))
103                    .collect(Collectors.toMap(Function.identity(), duplicatesMap::get));
104            
105            Map<Content, List<Content>> filteredNearDuplicatesMap = nearDuplicatesMap.keySet()
106                    .stream()
107                    .filter(WebContent.class::isInstance)
108                    .map(WebContent.class::cast)
109                    .filter(content -> site.equals(content.getSite()))
110                    .collect(Collectors.toMap(Function.identity(), nearDuplicatesMap::get));
111            
112            Map<Content, Status> filteredTooComplexMap = tooComplexMap.keySet()
113                    .stream()
114                    .filter(WebContent.class::isInstance)
115                    .map(WebContent.class::cast)
116                    .filter(content -> site.equals(content.getSite()))
117                    .collect(Collectors.toMap(Function.identity(), tooComplexMap::get));
118            
119            if (!filteredDuplicatesMap.isEmpty() || !filteredNearDuplicatesMap.isEmpty() || !filteredTooComplexMap.isEmpty())
120            {
121
122                body.append("<li>");
123                body.append(site.getTitle());
124                body.append("<ul>");
125                
126                body.append(super._displayContents(filteredDuplicatesMap, filteredNearDuplicatesMap, filteredTooComplexMap));
127
128                body.append("</ul>");
129                body.append("</li>");
130            }
131        }
132
133        Map<Content, List<Content>> filteredDuplicatesMap = duplicatesMap.keySet()
134                .stream()
135                .filter(Predicate.not(WebContent.class::isInstance))
136                .collect(Collectors.toMap(Function.identity(), duplicatesMap::get));
137        
138        Map<Content, List<Content>> filteredNearDuplicatesMap = nearDuplicatesMap.keySet()
139                .stream()
140                .filter(Predicate.not(WebContent.class::isInstance))
141                .collect(Collectors.toMap(Function.identity(), nearDuplicatesMap::get));
142        
143        Map<Content, Status> filteredTooComplexMap = tooComplexMap.keySet()
144                .stream()
145                .filter(Predicate.not(WebContent.class::isInstance))
146                .collect(Collectors.toMap(Function.identity(), tooComplexMap::get));
147        
148        if (!filteredDuplicatesMap.isEmpty() || !filteredNearDuplicatesMap.isEmpty() || !filteredTooComplexMap.isEmpty())
149        {
150            body.append("<li>");
151            body.append(_i18nUtils.translate(new I18nizableText("plugin.web", "PLUGINS_CMS_DUPLICATE_CONTENTS_GLOBAL_DETECTION_MAIL_BODY_DETECTED")));
152            body.append("<ul>");
153            
154            body.append(super._displayContents(filteredDuplicatesMap, filteredNearDuplicatesMap, filteredTooComplexMap));
155
156            body.append("</ul>");
157            body.append("</li>");
158        }
159        body.append("</ul>");
160        
161        return body.toString();
162    }
163}