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}