package net.krautchan.data;
/*
* Copyright (C) 2011 Johannes Jander (johannes@jandermail.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import junit.framework.Assert;
import org.apache.commons.lang3.StringEscapeUtils;
public class KCThread extends KrautObject {
private static final long serialVersionUID = -8659957154306651426L;
private static transient final SimpleDateFormat df = new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss z");
private static transient final SimpleDateFormat dfShort = new SimpleDateFormat ("dd.MM. HH:mm");
public Long kcNummer = null;
public Long board_id = null;
public Long firstPostDate = null;
public Long lastPostDate = null;
public String title = null;
public String digest = null;
public boolean hidden = false;
public boolean bookmarked = false;
public Long visited = null;
public Long previousLastKcNum = null;
public transient int numPostings = 0;
private TreeSet<KCPosting> postings = new TreeSet<KCPosting>();
public KCThread () {
}
public KCThread (String uri) {
this.uri = uri;
dbId = (long)uri.hashCode();
}
public synchronized KCPosting getPosting (Long id) {
for (KCPosting posting : postings) {
if (posting.dbId.compareTo(id) == 0) {
return posting;
}
}
return null;
}
public synchronized KCPosting getFirstPosting () {
if (!postings.isEmpty()) {
return postings.first();
}
return null;
}
public synchronized KCPosting getLastPosting() {
if (!postings.isEmpty()) {
return postings.last();
}
return null;
}
public boolean containsPosting (KCPosting posting) {
return postings.contains(posting);
}
public synchronized void addPosting (KCPosting posting) {
if (null == kcNummer) {
kcNummer = posting.kcNummer;
}
if (null == firstPostDate) {
firstPostDate = posting.created;
makeDigest (posting);
}
if (null == uri) {
uri = posting.uri;
}
if (null == dbId) {
dbId = (long)uri.hashCode();
}
if (null == digest) {
makeDigest (posting);
}
if (null == title) {
title = posting.title;
}
lastPostDate = posting.created;
if (!postings.contains(posting)) {
posting.threadId = dbId;
postings.add(posting);
}
Assert.assertNotNull(dbId);
}
public void doneLoading () {
try {
KCPosting posting = postings.first();
if (null == digest) {
makeDigest (posting);
}
if (null == title) {
this.title = posting.title;
}
if (null == firstPostDate) {
firstPostDate = posting.created;
}
if ((null == dbId) && (null != uri)) {
dbId = (long)uri.hashCode();
}
posting = postings.last();
if ((null == previousLastKcNum) || (previousLastKcNum < posting.kcNummer)) {
previousLastKcNum = posting.kcNummer;
}
Assert.assertNotNull(dbId);
} catch (Exception e) {
String trace = "Exception in KCThread "+kcNummer+" "+e.getClass().getCanonicalName()+"\n";
for (StackTraceElement elem : e.getStackTrace()) {
trace+= " "+elem.toString()+"\n";
}
System.err.println (trace);
}
}
public synchronized void clearPostings () {
postings.clear();
}
public synchronized Collection<Long> getIds () {
Collection<Long> ids = new ArrayList<Long>();
for (KCPosting posting: postings) {
ids.add(posting.dbId);
}
return ids;
}
public synchronized Set<KCPosting> getSortedPostings () {
TreeSet<KCPosting> s = new TreeSet<KCPosting>();
s.addAll(postings);
return s;
}
private void makeDigest (KCPosting posting) {
if (null == posting) {
return;
}
digest = posting.content;
int len = digest.length();
if (len > 250)
len = 250;
digest = digest.substring(0, len);
digest = digest.replaceAll("[\n\r\u0085\u2028\u2029]", " ").replaceAll(" +", " ").trim();
digest = StringEscapeUtils.unescapeHtml4(digest);
digest = digest.replaceAll("<span class=\"spoiler\">.+?</span>", "");
digest = digest.replaceAll("\\<.*?\\>", " ");
digest = digest.replaceAll("https?://.+? ", " ");
digest = digest.replaceAll(" +", " ");
len = digest.length();
if (len > 200)
len = 200;
digest = digest.substring(0, len);
digest = digest.replaceAll("\\<.*", "");
int pos = digest.length()-1;
char c = digest.charAt(pos);
while ((c != ' ') && (pos > 150)) {
pos--;
c = digest.charAt(pos);
}
digest = digest.trim();
for (String img : posting.thumbs) {
if ((img != null) && (img.length() > 0)) {
digest += "\n "+img;
}
}
}
public String toString() {
String d = null;
if (digest.length() > 39) {
d = digest.substring(0, 40);
} else {
d = digest;
}
return "Thread: "+uri+"\n"
+" KC Number: "+kcNummer+"\n"
+" DB ID: "+dbId+"\n"
+" Board: "+board_id+"\n"
+" Digest: "+d+"..."+"\n"
+" First posting: "+firstPostDate+"\n"
+" Last posting: "+lastPostDate+"\n"
;
}
@Override
public int hashCode () {
return toString().hashCode();
}
@Override
public boolean equals (Object arg0) {
if (!(arg0 instanceof KCThread)) {
return false;
}
if ((dbId != null) && (((KCThread)arg0).dbId != null)) {
return dbId.longValue() == ((KCThread)arg0).dbId.longValue();
}
return uri.equalsIgnoreCase( ((KCThread)arg0).uri);
}
}