/* * WPCleaner: A tool to help on Wikipedia maintenance tasks. * Copyright (C) 2013 Nicolas Vervelle * * See README.txt file for licensing information. */ package org.wikipediacleaner.gui.swing.worker; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wikipediacleaner.api.APIException; import org.wikipediacleaner.api.MediaWiki; import org.wikipediacleaner.api.constants.EnumWikipedia; import org.wikipediacleaner.api.constants.WPCConfigurationBoolean; import org.wikipediacleaner.api.constants.WPCConfigurationString; import org.wikipediacleaner.api.data.InternalLinkCount; import org.wikipediacleaner.api.data.Namespace; import org.wikipediacleaner.api.data.Page; import org.wikipediacleaner.api.data.PageAnalysis; import org.wikipediacleaner.api.data.PageElementTemplate; import org.wikipediacleaner.gui.swing.basic.BasicWindow; import org.wikipediacleaner.gui.swing.basic.BasicWorker; import org.wikipediacleaner.i18n.GT; /** * Tools for updating disambiguation warnings. */ public class UpdateDabWarningTools extends UpdateWarningTools { private final static Log log = LogFactory.getLog(UpdateDabWarningTools.class); private final Map<String, Page> dabPages; private final Map<String, Page> nonDabPages; /** True if links are already available in pages. */ private boolean linksAvailable; /** True if disambiguation information is already available in pages. */ private boolean dabInformationAvailable; /** * @param wiki Wiki. * @param worker Worker. * @param createWarning Create warning if necessary. * @param automaticEdit True if the edits are automatic. */ public UpdateDabWarningTools( EnumWikipedia wiki, BasicWorker worker, boolean createWarning, boolean automaticEdit) { this(wiki, worker, (worker != null) ? worker.getWindow() : null, createWarning, automaticEdit); } /** * @param wiki Wiki. * @param window Window. * @param createWarning Create warning if necessary. */ public UpdateDabWarningTools(EnumWikipedia wiki, BasicWindow window, boolean createWarning) { this(wiki, null, window, createWarning, false); } /** * @param wiki Wiki. * @param worker Worker. * @param window Window. * @param createWarning Create warning if necessary. * @param automaticEdit True if the edits are automatic. */ private UpdateDabWarningTools( EnumWikipedia wiki, BasicWorker worker, BasicWindow window, boolean createWarning, boolean automaticEdit) { super(wiki, worker, window, createWarning, automaticEdit); this.dabPages = new HashMap<String, Page>(); this.nonDabPages = new HashMap<String, Page>(); } /** * @param available True if links are already available in pages. */ public void setLinksAvailable(boolean available) { this.linksAvailable = available; } /** * @param available True if disambiguation information is already available in pages. */ public void setDabInformationAvailable(boolean available) { this.dabInformationAvailable = available; } /** * Load all disambiguation pages. */ public void preloadDabPages() { dabPages.clear(); nonDabPages.clear(); try { wiki.loadDisambiguationPages(api); } catch (APIException e) { log.error("Error preloading disambiguation pages", e); } } /** * Retrieve information in the pages to construct the warning. * * @param pages List of pages. * @return True if information was retrieved. * @throws APIException */ @Override protected boolean retrievePageInformation( List<Page> pages) throws APIException { MediaWiki mw = MediaWiki.getMediaWikiAccess(worker); // Retrieving links in each page if (!linksAvailable) { for (Page page : pages) { mw.retrieveAllLinks(wiki, page, Namespace.MAIN, null, false, false); } mw.block(true); if (shouldStop()) { return false; } } // Retrieving disambiguation information in each page boolean hasDisambiguationLink = false; if (!dabInformationAvailable) { if (!wiki.isDisambiguationPagesLoaded()) { List<Page> tmpPages = new ArrayList<Page>(); for (Page page : pages) { for (int numLink = 0; numLink < page.getLinks().size(); numLink++) { Page link = page.getLinks().get(numLink); if (dabPages.containsKey(link.getTitle())) { page.getLinks().set(numLink, dabPages.get(link.getTitle())); hasDisambiguationLink = true; } else if (nonDabPages.containsKey(link.getTitle())) { page.getLinks().set(numLink, nonDabPages.get(link.getTitle())); } else { tmpPages.add(link); } } } if (!tmpPages.isEmpty()) { mw.retrieveDisambiguationInformation(wiki, tmpPages, null, false, false, true); } for (Page page : tmpPages) { if (Boolean.TRUE.equals(page.isDisambiguationPage())) { dabPages.put(page.getTitle(), page); hasDisambiguationLink = true; } else { nonDabPages.put(page.getTitle(), page); } } } else { for (Page page : pages) { List<Page> links = page.getLinksWithRedirect(); for (int numLink = 0; numLink < links.size(); numLink++) { Page link = links.get(numLink); if (Boolean.TRUE.equals(wiki.isDisambiguationPage(link))) { link.setDisambiguationPage(Boolean.TRUE); hasDisambiguationLink = true; } else { link.setDisambiguationPage(Boolean.FALSE); } } } } if (shouldStop()) { return false; } } // Retrieving page contents if (hasDisambiguationLink && !getContentsAvailable()) { List<Page> tmpPages = new ArrayList<Page>(); for (Page page : pages) { boolean toAdd = false; for (Page link : page.getLinks()) { if (Boolean.TRUE.equals(link.isDisambiguationPage())) { toAdd = true; } } if (toAdd) { tmpPages.add(page); } } if (!tmpPages.isEmpty()) { mw.retrieveContents(wiki, tmpPages, true, false, false, false); } } return true; } /** * Extract links to disambiguation pages. * * @param analysis Page analysis (must have enough information to compute the list of disambiguation links). * @param talkPage Talk page. * @param todoSubpage to do sub-page. * @return List of links to disambiguation pages. */ @Override protected Collection<String> constructWarningElements( PageAnalysis analysis, Page talkPage, Page todoSubpage) { if ((analysis == null) || (analysis.getPage() == null)) { return null; } List<String> dabLinks = new ArrayList<String>(); List<Page> links = analysis.getPage().getLinks(); if (links != null) { // List disambiguation links in the page analysis.countLinks(links); for (Page link : links) { if (Boolean.TRUE.equals(link.isDisambiguationPage())) { InternalLinkCount linkCount = analysis.getLinkCount(link); if (linkCount != null) { if ((linkCount.getInternalLinkCount() > 0) || (linkCount.getIncorrectTemplateCount() > 0) || (linkCount.getHelpNeededCount() > 0)) { String error = link.getTitle(); dabLinks.add(error); memorizeError(error, analysis.getPage().getTitle()); } } } } // Remove links marked as normal cleanDabList(dabLinks, talkPage); cleanDabList(dabLinks, todoSubpage); } Collections.sort(dabLinks); return dabLinks; } /** * Remove disambiguation links marked as normal from the list. * * @param dabList List of disambiguation links. * @param page Page containing the list of normal disambiguation links. */ private void cleanDabList(Collection<String> dabList, Page page) { if ((dabList == null) || (page == null)) { return; } String okTemplate = configuration.getString(WPCConfigurationString.DAB_OK_TEMPLATE); if ((okTemplate == null) || okTemplate.trim().isEmpty()) { return; } okTemplate = okTemplate.trim(); PageAnalysis analysis = page.getAnalysis(page.getContents(), false); List<PageElementTemplate> templates = analysis.getTemplates(okTemplate); if ((templates == null) || templates.isEmpty()) { return; } for (PageElementTemplate template : templates) { boolean done = false; int numParam = 1; while (!done) { String link = template.getParameterValue(Integer.toString(numParam)); if (link == null) { done = true; } else { Iterator<String> itDab = dabList.iterator(); while (itDab.hasNext()) { String dab = itDab.next(); if (Page.areSameTitle(dab, link)) { itDab.remove(); } } numParam++; } } } } // ========================================================================== // Configuration // ========================================================================== /** * @return Configuration parameter for the warning template. */ @Override protected WPCConfigurationString getWarningTemplate() { return WPCConfigurationString.DAB_WARNING_TEMPLATE; } /** * @return Configuration parameter for the warning template comment. */ @Override protected WPCConfigurationString getWarningTemplateComment() { return WPCConfigurationString.DAB_WARNING_TEMPLATE_COMMENT; } /** * @return Configuration parameter for the title for a message for a new article. */ @Override protected WPCConfigurationString getMessageTitleNewArticle() { return WPCConfigurationString.MSG_NEW_ARTICLE_WITH_DAB_TITLE; } /** * @return Configuration parameter for the title for a message for a new article. */ @Override protected WPCConfigurationString getMessageTitleNewArticleModified() { return WPCConfigurationString.MSG_NEW_ARTICLE_MODIFIED_WITH_DAB_TITLE; } /** * @return Configuration parameter for the title for a message for a new article. */ @Override protected WPCConfigurationString getMessageTitleNewArticleModifier() { return WPCConfigurationString.MSG_NEW_ARTICLE_MODIFIER_WITH_DAB_TITLE; } /** * @return Configuration parameter for the template for a message for a new article. */ @Override protected WPCConfigurationString getMessageTemplateNewArticle() { return WPCConfigurationString.MSG_NEW_ARTICLE_WITH_DAB_TEMPLATE; } /** * @return Configuration parameter for the template for a message for a new article. */ @Override protected WPCConfigurationString getMessageTemplateNewArticleModified() { return WPCConfigurationString.MSG_NEW_ARTICLE_MODIFIED_WITH_DAB_TEMPLATE; } /** * @return Configuration parameter for the template for a message for a new article. */ @Override protected WPCConfigurationString getMessageTemplateNewArticleModifier() { return WPCConfigurationString.MSG_NEW_ARTICLE_MODIFIER_WITH_DAB_TEMPLATE; } /** * @return True if section 0 of the talk page should be used. */ @Override protected boolean useSection0() { return configuration.getBoolean(WPCConfigurationBoolean.DAB_WARNING_SECTION_0); } /** * @return Comment when warning is removed. */ @Override protected String getWarningCommentDone() { return configuration.getDisambiguationWarningCommentDone(); } /** * @param elements Message elements. * @return Comment when warning is added or updated. */ @Override protected String getWarningComment(Collection<String> elements) { return configuration.getDisambiguationWarningComment(elements); } /** * @param title Page title. * @return Message displayed when removing the warning from the page. */ @Override protected String getMessageRemoveWarning(String title) { return GT._("Removing disambiguation warning - {0}", title); } /** * @param title Page title. * @return Message displayed when updating the warning from the page. */ @Override protected String getMessageUpdateWarning(String title) { return GT._("Updating disambiguation warning - {0}", title); } }