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 content helper */
046    protected ContentHelper _contentHelper;
047    
048    /** The extension point for site getters */
049    protected SiteGetterExtensionPoint _siteGetterExtensionPoint;
050
051    /** The site manager. */
052    protected SiteManager _siteManager;
053    
054    @Override
055    public void service(ServiceManager manager) throws ServiceException
056    {
057        super.service(manager);
058        _contentHelper = (ContentHelper) manager.lookup(ContentHelper.ROLE);
059        _siteGetterExtensionPoint = (SiteGetterExtensionPoint) manager.lookup(SiteGetterExtensionPoint.ROLE);
060        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
061    }
062    
063    /**
064     * Render the cms tool link
065     * @param content The content
066     * @return the link
067     */
068    @Override
069    protected String _renderCmsToolLink(Content content)
070    {
071        StringBuilder url = new StringBuilder();
072
073        Optional<Site> site = _siteGetterExtensionPoint.getSiteByContent(content);
074     
075        if (site.isPresent())
076        {
077            url.append("<a href=\"");
078            url.append(_baseUrl);
079            url.append("/");
080            url.append(site.get().getName());
081            url.append("/index.html?uitool=uitool-content,id:%27");
082            url.append(content.getId());
083            url.append("%27\">");
084            url.append(content.getTitle());
085            url.append("</a>");
086        }
087        else
088        {
089            url.append(content.getTitle());
090        }
091        return url.toString();
092    }
093    
094    @Override
095    protected StringBuilder _displayContents(Map<Content, List<Content>> duplicatesMap, Map<Content, List<Content>> nearDuplicatesMap,
096            Map<Content, DuplicateContentsManager.Status> tooComplexMap)
097    {
098
099        AmetysObjectIterable<Site> sites = _siteManager.getSites();
100        StringBuilder body = new StringBuilder();
101        body.append("<ul>");
102        for (Site site : sites)
103        {
104            Map<Content, List<Content>> filteredDuplicatesMap = duplicatesMap.keySet()
105                    .stream()
106                    .filter(WebContent.class::isInstance)
107                    .map(WebContent.class::cast)
108                    .filter(content -> site.equals(content.getSite()))
109                    .collect(Collectors.toMap(Function.identity(), duplicatesMap::get));
110            
111            Map<Content, List<Content>> filteredNearDuplicatesMap = nearDuplicatesMap.keySet()
112                    .stream()
113                    .filter(WebContent.class::isInstance)
114                    .map(WebContent.class::cast)
115                    .filter(content -> site.equals(content.getSite()))
116                    .collect(Collectors.toMap(Function.identity(), nearDuplicatesMap::get));
117            
118            Map<Content, Status> filteredTooComplexMap = tooComplexMap.keySet()
119                    .stream()
120                    .filter(WebContent.class::isInstance)
121                    .map(WebContent.class::cast)
122                    .filter(content -> site.equals(content.getSite()))
123                    .collect(Collectors.toMap(Function.identity(), tooComplexMap::get));
124            
125            if (!filteredDuplicatesMap.isEmpty() || !filteredNearDuplicatesMap.isEmpty() || !filteredTooComplexMap.isEmpty())
126            {
127
128                body.append("<li>");
129                body.append(site.getTitle());
130                body.append("<ul>");
131                
132                body.append(super._displayContents(filteredDuplicatesMap, filteredNearDuplicatesMap, filteredTooComplexMap));
133
134                body.append("</ul>");
135                body.append("</li>");
136            }
137        }
138
139        Map<Content, List<Content>> filteredDuplicatesMap = duplicatesMap.keySet()
140                .stream()
141                .filter(Predicate.not(WebContent.class::isInstance))
142                .collect(Collectors.toMap(Function.identity(), duplicatesMap::get));
143        
144        Map<Content, List<Content>> filteredNearDuplicatesMap = nearDuplicatesMap.keySet()
145                .stream()
146                .filter(Predicate.not(WebContent.class::isInstance))
147                .collect(Collectors.toMap(Function.identity(), nearDuplicatesMap::get));
148        
149        Map<Content, Status> filteredTooComplexMap = tooComplexMap.keySet()
150                .stream()
151                .filter(Predicate.not(WebContent.class::isInstance))
152                .collect(Collectors.toMap(Function.identity(), tooComplexMap::get));
153        
154        if (!filteredDuplicatesMap.isEmpty() || !filteredNearDuplicatesMap.isEmpty() || !filteredTooComplexMap.isEmpty())
155        {
156            body.append("<li>");
157            body.append(_i18nUtils.translate(new I18nizableText("plugin.web", "PLUGINS_CMS_DUPLICATE_CONTENTS_GLOBAL_DETECTION_MAIL_BODY_DETECTED")));
158            body.append("<ul>");
159            
160            body.append(super._displayContents(filteredDuplicatesMap, filteredNearDuplicatesMap, filteredTooComplexMap));
161
162            body.append("</ul>");
163            body.append("</li>");
164        }
165        body.append("</ul>");
166        
167        return body;
168    }
169}