/*
* 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.bo;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import org.priki.utils.SortedBag;
import org.priki.utils.StringMap;
import org.priki.utils.WikiwordIndex;
import org.priki.utils.WikiwordUtils;
/**
* Class to hold all element intances. The Base of the system.
* This class is a singleton.
*
* @author <a href="mailto:vitor@babaxp.org">Vitor Fernando Pamplona</a>
*
* @since 14/10/2005
* @version $Id: $
*/
public class Wiki implements Serializable {
public static final long serialVersionUID = 1L;
private StringMap<Element> elements;
@Deprecated
private StringMap<Wikiword> words;
private WikiwordIndex wordsIndex;
private Admin admin;
private Police police;
public Admin getAdmin() {
if (admin == null) {
admin = new Admin();
}
return admin;
}
public Police getPolice() {
if (police == null) {
police = new Police(3);
}
return police;
}
private StringMap<Element> elements() {
if (elements == null)
elements = new StringMap<Element>();
return elements;
}
private WikiwordIndex words() {
if (wordsIndex == null) {
wordsIndex = new WikiwordIndex();
}
if (words != null && words.size() > wordsIndex.size()) {
// Translate from old index to the new one
wordsIndex.putAll(words);
}
return wordsIndex;
}
public int getElementCount() {
return elements().size();
}
public int getWikiwordCount() {
return words().size();
}
public Element getElement(String keyword) {
return elements().get(keyword);
}
public Wikiword getWikiword(String keyword) {
return words().get(keyword);
}
public Wikiword getWikiwordIgnoreCase(String keyword) {
Collection<Wikiword> wikiwords = getWikiwordsIgnoreCase(keyword);
for (Wikiword wikiword : wikiwords) {
if (WikiwordUtils.equalsKeyword(keyword, wikiword)) {
return wikiword;
}
}
return null;
}
public Collection<Wikiword> getWikiwordsIgnoreCase(String keyword) {
return words().getIgnoreCase(keyword);
}
public void rename(String oldWikiword, String newWikiword) {
if (oldWikiword.equals(newWikiword)) return;
Wikiword oldW = getWikiword(oldWikiword);
Wikiword newW = newWikiword(newWikiword);
newW.copy(oldW);
oldW.clean();
}
public boolean hasElement(String keyword) {
return elements().containsKey(keyword);
}
public boolean hasWikiword(String keyword) {
return words().containsKey(keyword);
}
public boolean hasWikiwordIgnoreCase(String keyword) {
Collection<Wikiword> wikiwords = getWikiwordsIgnoreCase(keyword);
for (Wikiword wikiword : wikiwords) {
if (WikiwordUtils.equalsKeyword(keyword, wikiword)) {
return true;
}
}
return false;
}
/** Return an existing or new element in this class. If it doesn't exist, create a new one. */
public Element newElement(String keyword) {
Element e = getElement(keyword);
if (e == null) {
e = new Element(keyword);
elements().put(keyword, e);
}
return e;
}
/** Return an existing or new wikiword in this class. If it doesn't exist, create a new one. */
public Wikiword newWikiword(String keyword) {
Wikiword e = getWikiword(keyword);
if (e == null) {
e = new Wikiword(keyword);
words().put(keyword, e);
}
return e;
}
public void removeElement(Element reference) {
elements().remove(reference.getKeyword());
}
public void removeWikiword(Wikiword reference) {
words().remove(reference.getKeyword());
}
/** Clear all */
public void clear() {
elements().clear();
words().clear();
getAdmin().getAccessManager().clear();
getPolice().clear();
}
public Collection<Wikiword> wordsStartingWith(String keyword) {
return words().startingWith(keyword);
}
public List<String> getElements() {
return new ArrayList<String>(elements().keySet());
}
public List<String> getWikiwords() {
return new ArrayList<String>(words().keySet());
}
/*
public Map<Date, Wikiword> lastChanged() {
Calendar calLimit = (Calendar) Calendar.getInstance().clone();
calLimit.add(Calendar.DAY_OF_MONTH, -getAdmin().getLastChangesCount());
return lastChangedAfter(calLimit.getTime());
}
/** returns the last changed elements after the date.
public SortedMap<Date, Wikiword> lastChangedAfter(Date date) {
SortedMap<Date, Wikiword> map = new TreeMap<Date, Wikiword>(Collections.reverseOrder());
Date temp;
for (Wikiword e : words().values()) {
if (getAdmin().isLastChangesOnlyNewPages()) {
if (e.hasFirstDefinitionDateAfter(date)) {
map.put(e.getFirstDefinitionDate(), e);
}
} else {
if (e.hasLastDefinitionDateAfter(date)) {
map.put(e.getLastDefinitionDate(), e);
} else if ((temp = e.hasCommentAfter(date)) != null) {
map.put(temp, e);
}
}
}
return map;
}*/
/** returns the last changed elements after the date. */
public SortedMap<Date, Wikiword> lastChangedFull(String user) {
SortedMap<Date, Wikiword> map = new TreeMap<Date, Wikiword>(Collections.reverseOrder());
if (getAdmin().isLastChangesOnlyNewPages()) {
for (Wikiword e : words().values()) {
if (e.hasDefinition() && getAdmin().getAccessManager().iCanRead(user, e)) {
map.put(e.getFirstDefinitionDate(), e);
}
}
} else {
for (Wikiword e : words().values()) {
if (e.hasDefinition() && getAdmin().getAccessManager().iCanRead(user, e)) {
Date lastDef = e.getLastDefinitionDate();
Date lastComm = e.getLastCommentPostDate();
Date last;
if (lastComm == null)
last = lastDef;
else
last = lastDef.after(lastComm) ? lastDef : lastComm;
map.put(last, e);
}
}
}
return map;
}
/** returns the last changed elements after the date. */
public SortedBag<Wikiword> getGlobalTags() {
SortedBag<Wikiword> bag = new SortedBag<Wikiword>();
for (Wikiword e : words().values()) {
if (e.hasDefinition()) {
bag.addAll(e.getTags());
}
}
return bag;
}
public SortedMap<Date, Wikiword> changedByUser(String user) {
SortedMap<Date, Wikiword> map = new TreeMap<Date, Wikiword>();
Date date;
for (Wikiword e : words().values()) {
if (user.equalsIgnoreCase(e.getLastDefinitionUser())) {
map.put(e.getLastDefinitionDate(), e);
} else if ((date = e.hasCommentBy(user)) != null) {
map.put(date, e);
}
}
return map;
}
public List<Wikiword> wikiwordsChangedAfter(Date date) {
List<Wikiword> ret = new ArrayList<Wikiword>();
for (Wikiword e : words().values()) {
if (e.hasLastDefinitionDateAfter(date)) {
ret.add(e);
}
}
return ret;
}
public String fixWikiRefers() {
String result = "";
for (Wikiword w : words().values()) {
for (Wikiword related : new ArrayList<Wikiword>(w.getRelated())) {
if (!related.hasDefinition()) {
w.removeRelated(related);
related.clearTags();
related.clearComments();
result += "\"" + w.getKeyword() + "\" has a related page called \"" + related.getKeyword() + "\", but it does not has any definition. Removing related word.\n";
} else if (!related.isTalkingAbout(w)) {
w.removeRelated(related);
result += "\""+ w.getKeyword() + "\" has a related page called \"" + related.getKeyword() + "\", but it is not used in the current text and it is not cited in tags. Removing related word.\n";
}
}
}
return result;
}
// cleaning unrelated words.
// called after each post
public void cleanUnusedWikiwords() {
List<Wikiword> toRemove = new ArrayList<Wikiword>();
for (Wikiword w : words().values()) {
if (!w.isUsed())
toRemove.add(w);
}
for (Wikiword w : toRemove) {
words().remove(w.getKeyword());
}
}
public void removeAllComments() {
for (Wikiword w : words().values()) {
w.clearComments();
}
}
/** Search by an element */
public Collection<Wikiword> search(String keyword) {
return words().searchByAnythingWith(keyword);
}
/** RollBack all posts that were posted after the date, by the user ip
* Mark the removed posts as bad posts in the police. */
public void setBadUser(Date since, String userIP) {
List<Wikiword> changes = wikiwordsChangedAfter(since);
List<Text> bads = new ArrayList<Text>();
List<Text> temp;
for (Wikiword changed : changes) {
temp = changed.removeDefinitions(since, userIP);
if (temp != null && temp.size() > 0)
bads.addAll(temp);
}
getPolice().setBadTexts(bads);
getPolice().setBadUser(userIP);
}
}