/* * Priki - Prevalent Wiki * Copyright (c) 2005 Priki * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * http://www.gnu.org/copyleft/gpl.html * * @author Vitor Fernando Pamplona - vitor@babaxp.org * */ package org.priki.prevalence; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.priki.bo.Text; import org.priki.bo.User; import org.priki.bo.Wiki; import org.priki.bo.Wikiword; import org.priki.format.FormatPrevalenceFactory; import org.priki.format.Formatter; import org.priki.format.Parser; import org.priki.prevalence.exceptions.ConflictingWikiwordsException; import org.priki.prevalence.exceptions.PoliceException; import org.priki.utils.StringUtils; public class ParserTransaction extends PrikiTransaction { public static final long serialVersionUID = 1L; private String user; private Date postDate = new Date(); private String wikiword; private String text; private boolean caseSensitive; private Wikiword.Visibility visibility; private String newWikiword; private List<String> tags; private Formatter wikiFormatter; private Parser wikiParser; public ParserTransaction(String user, String wikiword, String text, boolean caseSensitive) { this.user = user; this.wikiword = wikiword; this.text = text; this.caseSensitive = caseSensitive; tags = new ArrayList<String>(); } public ParserTransaction(String user, String wikiword, String text, boolean caseSensitive, Wikiword.Visibility vis) { this.user = user; this.wikiword = wikiword; this.text = text; this.caseSensitive = caseSensitive; this.visibility = vis; tags = new ArrayList<String>(); } public ParserTransaction(String user, String wikiword, String newWikiword, String text, boolean caseSensitive, Wikiword.Visibility vis, List<String> tags) { this.user = user; this.wikiword = wikiword; this.text = text; this.caseSensitive = caseSensitive; this.visibility = vis; this.newWikiword = newWikiword; this.tags = tags; } public Parser getParser(Wiki wiki) { if (wikiParser == null) wikiParser = FormatPrevalenceFactory.createDefaultParser(wiki); return wikiParser; } public Formatter getFormatter(Wiki wiki) { if (wikiFormatter == null) wikiFormatter = FormatPrevalenceFactory.createDefaultFormatter(wiki); return wikiFormatter; } public void checkCanPost(Wiki wiki, String user, Wikiword page) { if (!wiki.getAdmin().getAccessManager().iCanPost(user, page)) { throw new PoliceException(); } } public Text textFactory(Wiki wiki, String userByString, Date postDate) { User reggisteredUser = wiki.getAdmin().getAccessManager().getUser(user); if (reggisteredUser==null) return new Text(userByString, postDate); else return new Text(reggisteredUser, postDate); } public void executeOn(Wiki wiki) { // INSERT if (StringUtils.isNullAndBlank(wikiword)) { wikiword = newWikiword; } // Using first Constructor if (StringUtils.isNullAndBlank(newWikiword)) { newWikiword = wikiword; } Wikiword wOriginal = wiki.getWikiword(wikiword); checkCanPost(wiki, user, wOriginal); checkCanPost(wiki, user, wiki.getWikiword(newWikiword)); // rename first. if (wOriginal != null && !wikiword.equals(newWikiword)) { // Rename. wiki.rename(wikiword, newWikiword); } executeSimple(wiki, newWikiword); } private void executeSimple(Wiki wiki, String wikiword) { Parser parser = getParser(wiki); // Converts a simple wikiword in a composite wikiword. List<Wikiword> wikiwordsOfTitle = parser.getWikiwords(wikiword); // Creating the text and identifyng wiki words. Text textObject = textFactory(wiki, user, postDate); parser.parseText(text, textObject); if (!wiki.getPolice().isBadText(textObject)) { Wikiword e = wiki.newWikiword(wikiword); e.setCaseSensitive(caseSensitive); e.setVisibility(visibility); // check Case Sensitive Conflicts checkCaseSensitiveConflicts(wiki, e); e.clearTags(); for (String tag : tags) { e.addTag(wiki.newWikiword(tag)); } // Hold the wikiwords to be recompiled Set<Wikiword> toRecompile = new HashSet<Wikiword>(); toRecompile.addAll(handleCompositeWikiword(wiki, e, wikiwordsOfTitle)); toRecompile.addAll(handleCaseInsensitiveWikiword(wiki, e)); // Definition must be the last updating // Creating the text and identifyng wiki words. textObject = textFactory(wiki, user, postDate); parser.parseText(text, textObject); e.setDefinition(textObject); // Recompile the old wikiwords for (Wikiword word : toRecompile) { recompileWikiwordAndComments(wiki,word); } // clean unreferred wikiwords wiki.cleanUnusedWikiwords(); } } private Text recompileText(Wiki wiki, Text text) { String temp = getFormatter(wiki).formatWithoutLinks(text); Text otherText = new Text(text.getWhoPosted(), text.getPostDate()); getParser(wiki).parseText(temp, otherText); return otherText; } private void recompileWikiwordAndComments(Wiki wiki,Wikiword word) { if (word.hasDefinition()) word.setDefinition(recompileText(wiki, word.getDefinition())); List<Text> newComments = new ArrayList<Text>(); for (Text comm : word.getComments()) { if (comm != null && comm.getElementCount() > 0) newComments.add(recompileText(wiki, comm)); } word.clearComments(); for (Text comm : newComments) { word.addComment(comm); } } /** * Handle the situation where an insensitive wikiword is posted.<br> * Old undefinied wikiwords with same keyword are replaced by the new one.<br> * * @param wiki Wiki * @param word Wikiword * @return Set of wikiwords to be recompiled. */ private Set<Wikiword> handleCaseInsensitiveWikiword(Wiki wiki, Wikiword word) { // Ensure that it's insensitive if (word.isCaseSensitive()) { return Collections.emptySet(); } Set<Wikiword> toRecompile = new HashSet<Wikiword>(); Collection<Wikiword> starts = wiki.getWikiwordsIgnoreCase(word.getKeyword()); for (Wikiword old : starts) { // Itself, OK if (word == old) { continue; } // All related wikiwords to the old one, must be recompiled toRecompile.addAll(old.getRelated()); wiki.removeWikiword(old); } return toRecompile; } /** * Refresh wikiwords used in a composite wikiword. * <br><br> * If there are a text with this elements: "Vitor" "Fernando" "Pamplona"<br> * And a new wikiword is putted into the system: "Vitor Fernando Pamplona"<br> * This method will search the texts that are using "Vitor" "Fernando" "Pamplona" elements * and replaces it to the composite wikiword: "Vitor Fernando Pamplona" <br> * * @param wiki Wiki * @param word Wikiword * @param keyword List of keywords used in a composite keyword. * @return Set of wikiwords to be recompiled */ private Set<Wikiword> handleCompositeWikiword(Wiki wiki, Wikiword word, List<Wikiword> keyword) { Set<Wikiword> toRecompile = new HashSet<Wikiword>(); // Handle composite wikiword if (keyword.size() > 1) { // Related texts using the first word, must be recompiled if (word.isCaseSensitive()) { toRecompile.addAll(keyword.get(0).getRelated()); } else { Collection<Wikiword> equals = wiki.getWikiwordsIgnoreCase(keyword.get(0).getKeyword()); for (Wikiword old : equals) { toRecompile.addAll(old.getRelated()); } } } // Insensitive wikiword has an especial case // When wikiword "design patterns" is posted again and changed to insensitive, // and already exists a wikiword "Design", // the texts using this wikiword must be recompiled if (!word.isCaseSensitive()) { List<Wikiword> words = getParser(wiki).splitWikiword(word.getKeyword()); if (words.size() > keyword.size()) { Collection<Wikiword> equals = wiki.getWikiwordsIgnoreCase(words.get(0).getKeyword()); for (Wikiword old : equals) { toRecompile.addAll(old.getRelated()); } } } return toRecompile; } /** * Check if the wikiword conflicts with another wikiword.<br> * Insensitive wikiword conflicts with any defined wikiword with same keyword.<br> * Sensitive wikiword conflicts with any insensitive wikiword with same keyword.<br> * * @param wiki Wiki * @param word Wikiword * @throws @{@link ConflictingWikiwordsException} */ private static void checkCaseSensitiveConflicts(Wiki wiki, Wikiword word) { Collection<Wikiword> equals = wiki.getWikiwordsIgnoreCase(word.getKeyword()); for (Wikiword old : equals) { // Itself, OK if (word == old) { continue; } // There is no way to conflict two sensitive wikiwords if (word.isCaseSensitive() && old.isCaseSensitive()) { continue; } // Insensitive doest'n conflict with undefined wikiword if (old.getDefinition() == null) { continue; } throw new ConflictingWikiwordsException(old, word); } } }