From e7c2ea193bad4d749e462c33beb6b4fb619ab19c Mon Sep 17 00:00:00 2001 From: apfelmaennchen Date: Sun, 1 May 2011 21:42:48 +0000 Subject: [PATCH] YMark: - general improvements on importers, especially on auto tagging - added get_tags (needed for tag clouds etc.) - improved flexigrid support - added YMarks.html (not fully working) that will eventually replace Bookmarks.html git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@7691 6c8d7289-2bf4-0310-a012-ef5d649a1542 --- htroot/YMarks.html | 205 ++++++++++++++++++ htroot/YMarks.java | 27 +++ htroot/api/ymarks/add_ymark.java | 2 +- htroot/api/ymarks/get_tags.java | 104 +++++++++ htroot/api/ymarks/get_tags.xml | 5 + htroot/api/ymarks/get_ymark.java | 13 +- htroot/api/ymarks/get_ymark.json | 4 +- htroot/api/ymarks/import_ymark.java | 77 +++++-- htroot/api/ymarks/test_import.html | 24 +- htroot/yacy/ui/sidebar/sidebar_2.html | 2 +- .../data/ymark/TablesRowComparator.java | 1 - .../de/anomic/data/ymark/YMarkAutoTagger.java | 192 ++++++++++++++++ source/de/anomic/data/ymark/YMarkEntry.java | 24 +- .../anomic/data/ymark/YMarkHTMLImporter.java | 2 +- .../anomic/data/ymark/YMarkJSONImporter.java | 2 +- .../de/anomic/data/ymark/YMarkMetadata.java | 44 ---- source/de/anomic/data/ymark/YMarkTables.java | 130 +++++++---- source/de/anomic/data/ymark/YMarkTag.java | 46 ++++ .../anomic/data/ymark/YMarkXBELImporter.java | 40 ++-- 19 files changed, 795 insertions(+), 149 deletions(-) create mode 100644 htroot/YMarks.html create mode 100644 htroot/YMarks.java create mode 100644 htroot/api/ymarks/get_tags.java create mode 100644 htroot/api/ymarks/get_tags.xml create mode 100644 source/de/anomic/data/ymark/YMarkAutoTagger.java create mode 100644 source/de/anomic/data/ymark/YMarkTag.java diff --git a/htroot/YMarks.html b/htroot/YMarks.html new file mode 100644 index 000000000..dba13e80c --- /dev/null +++ b/htroot/YMarks.html @@ -0,0 +1,205 @@ + + + + YaCy '#[user]#''s Bookmarks + #%env/templates/metas.template%# + + + + + #%env/templates/header.template%# + + + + + +
+ + + +
+
+ #%env/templates/footer.template%# + + \ No newline at end of file diff --git a/htroot/YMarks.java b/htroot/YMarks.java new file mode 100644 index 000000000..872b58f98 --- /dev/null +++ b/htroot/YMarks.java @@ -0,0 +1,27 @@ +import net.yacy.cora.protocol.RequestHeader; +import de.anomic.data.UserDB; +import de.anomic.data.ymark.YMarkTables; +import de.anomic.search.Switchboard; +import de.anomic.server.serverObjects; +import de.anomic.server.serverSwitch; + +public class YMarks { + public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) { + final Switchboard sb = (Switchboard) env; + final serverObjects prop = new serverObjects(); + final UserDB.Entry user = sb.userDB.getUser(header); + final boolean isAdmin = (sb.verifyAuthentication(header, true)); + final boolean isAuthUser = user!= null && user.hasRight(UserDB.AccessRight.BOOKMARK_RIGHT); + + if(isAdmin || isAuthUser) { + prop.put("login", 1); + String bmk_user = (isAuthUser ? user.getUserName() : YMarkTables.USER_ADMIN); + prop.putHTML("user", bmk_user.substring(0,1).toUpperCase() + bmk_user.substring(1)); + + } else { + prop.put("login", 0); + } + + return prop; + } +} \ No newline at end of file diff --git a/htroot/api/ymarks/add_ymark.java b/htroot/api/ymarks/add_ymark.java index 7a772b26f..7edea60ea 100644 --- a/htroot/api/ymarks/add_ymark.java +++ b/htroot/api/ymarks/add_ymark.java @@ -43,7 +43,7 @@ public class add_ymark { bmk.put(YMarkEntry.BOOKMARK.FOLDERS.key(), YMarkUtil.cleanFoldersString(post.get(YMarkEntry.BOOKMARK.FOLDERS.key(),YMarkEntry.FOLDERS_UNSORTED))); try { - sb.tables.bookmarks.addBookmark(bmk_user, bmk, false); + sb.tables.bookmarks.addBookmark(bmk_user, bmk, false, false); } catch (IOException e) { Log.logException(e); } catch (RowSpaceExceededException e) { diff --git a/htroot/api/ymarks/get_tags.java b/htroot/api/ymarks/get_tags.java new file mode 100644 index 000000000..4321f7d47 --- /dev/null +++ b/htroot/api/ymarks/get_tags.java @@ -0,0 +1,104 @@ + +import java.io.IOException; +import java.text.CollationKey; +import java.text.Collator; +import java.util.Iterator; +import java.util.TreeMap; +import java.util.TreeSet; + +import net.yacy.cora.protocol.RequestHeader; +import de.anomic.data.UserDB; +import de.anomic.data.ymark.YMarkEntry; +import de.anomic.data.ymark.YMarkTables; +import de.anomic.data.ymark.YMarkTag; +import de.anomic.data.ymark.YMarkUtil; +import de.anomic.search.Switchboard; +import de.anomic.server.serverObjects; +import de.anomic.server.serverSwitch; + +public class get_tags { + + final static String TAG = "tag"; + final static String TOP = "top"; + final static String SORT = "sort"; + final static String SIZE = "size"; + final static String ALPHA = "alpha"; + + + private static Switchboard sb = null; + private static serverObjects prop = null; + + public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) { + sb = (Switchboard) env; + prop = new serverObjects(); + + final UserDB.Entry user = sb.userDB.getUser(header); + final boolean isAdmin = (sb.verifyAuthentication(header, true)); + final boolean isAuthUser = user!= null && user.hasRight(UserDB.AccessRight.BOOKMARK_RIGHT); + + if(isAdmin || isAuthUser) { + final String bmk_user = (isAuthUser ? user.getUserName() : YMarkTables.USER_ADMIN); + Integer top = Integer.MAX_VALUE; + Boolean sortAlpha = true; + Iterator tit = null; + TreeSet tags = null; + int count = 0; + YMarkTag t; + + if (post != null && post.containsKey(TAG)) { + if (!post.get(TAG).isEmpty()) { + final String[] tagArray = YMarkUtil.cleanTagsString(post.get(TAG)).split(YMarkUtil.TAGS_SEPARATOR); + try { + tags = new TreeSet(sb.tables.bookmarks.getTags(sb.tables.bookmarks.getBookmarksByTag(bmk_user, tagArray)).values()); + } catch (IOException e) { + return prop; + } + } + } else { + try { + tags = new TreeSet(sb.tables.bookmarks.getTags(bmk_user).values()); + } catch (IOException e) { + return prop; + } + } + + if (post != null && post.containsKey(TOP)) { + top = post.getInt(TOP, Integer.MAX_VALUE); + } + + if (post != null && post.containsKey(SORT)) { + if (SIZE.equals(post.get(SORT))) { + sortAlpha = false; + } + } + + if(sortAlpha) { + final TreeMap sort = new TreeMap(); + final Collator collator = Collator.getInstance(); + collator.setStrength(Collator.SECONDARY); + tit = tags.iterator(); + while(tit.hasNext() && count < top) { + t = tit.next(); + sort.put(collator.getCollationKey(t.name()), t); + count++; + } + tit = sort.values().iterator(); + } else { + tit = tags.iterator(); + } + + count = 0; + while (tit.hasNext() && count < top) { + t = tit.next(); + if(!t.name().equals(YMarkEntry.BOOKMARK.TAGS.deflt())) { + prop.putXML("tags_" + count + "_name", t.name()); + prop.put("tags_" + count + "_count", t.size()); + count++; + } + } + + prop.put("tags", count); + } + return prop; + } +} diff --git a/htroot/api/ymarks/get_tags.xml b/htroot/api/ymarks/get_tags.xml new file mode 100644 index 000000000..6c58ea8fb --- /dev/null +++ b/htroot/api/ymarks/get_tags.xml @@ -0,0 +1,5 @@ + + +#{tags}# +#{/tags}# + \ No newline at end of file diff --git a/htroot/api/ymarks/get_ymark.java b/htroot/api/ymarks/get_ymark.java index d86a33990..82622880e 100644 --- a/htroot/api/ymarks/get_ymark.java +++ b/htroot/api/ymarks/get_ymark.java @@ -9,8 +9,10 @@ import net.yacy.kelondro.blob.Tables; import net.yacy.kelondro.blob.Tables.Row; import net.yacy.kelondro.logging.Log; import de.anomic.data.UserDB; +import de.anomic.data.ymark.YMarkDate; import de.anomic.data.ymark.YMarkEntry; import de.anomic.data.ymark.YMarkTables; +import de.anomic.data.ymark.YMarkUtil; import de.anomic.data.ymark.YMarkTables.TABLES; import de.anomic.search.Switchboard; import de.anomic.server.serverObjects; @@ -21,6 +23,7 @@ public class get_ymark { private static Switchboard sb = null; private static serverObjects prop = null; + final static String FOLDER_IMG = ""; public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) { sb = (Switchboard) env; @@ -64,7 +67,7 @@ public class get_ymark { query = ".*"; try { final String bmk_table = TABLES.BOOKMARKS.tablename(bmk_user); - final Collection result = sb.tables.bookmarks.orderBy(sb.tables.iterator(bmk_table, qtype, Pattern.compile(query)), sortname, sortorder); + final Collection result = sb.tables.bookmarks.orderBookmarksBy(sb.tables.iterator(bmk_table, qtype, Pattern.compile(query)), sortname, sortorder); total = result.size(); bookmarks = result.iterator(); } catch (IOException e) { @@ -136,7 +139,13 @@ public class get_ymark { prop.put("json_"+count+"_hash", UTF8.String(bmk_row.getPK())); for (YMarkEntry.BOOKMARK bmk : YMarkEntry.BOOKMARK.values()) { if(bmk == YMarkEntry.BOOKMARK.PUBLIC) - prop.put("json_"+count+"_"+bmk.key(), bmk_row.get(bmk.key(),bmk.deflt()).equals("true") ? 1 : 0); + prop.put("json_"+count+"_"+bmk.key(), bmk_row.get(bmk.key(),bmk.deflt()).equals("true") ? 0 : 1); + else if(bmk == YMarkEntry.BOOKMARK.TAGS) + prop.putJSON("json_"+count+"_"+bmk.key(), bmk_row.get(bmk.key(),bmk.deflt()).replaceAll(YMarkUtil.TAGS_SEPARATOR, ", ")); + else if(bmk == YMarkEntry.BOOKMARK.FOLDERS) + prop.putJSON("json_"+count+"_"+bmk.key(), bmk_row.get(bmk.key(),bmk.deflt()).replaceAll(YMarkUtil.TAGS_SEPARATOR, "
"+FOLDER_IMG)); + else if(bmk == YMarkEntry.BOOKMARK.DATE_ADDED || bmk == YMarkEntry.BOOKMARK.DATE_MODIFIED || bmk == YMarkEntry.BOOKMARK.DATE_VISITED) + prop.putJSON("json_"+count+"_"+bmk.key(), (new YMarkDate(bmk_row.get(bmk.key()))).toISO8601().replaceAll("T", "
")); else prop.putJSON("json_"+count+"_"+bmk.key(), bmk_row.get(bmk.key(),bmk.deflt())); } diff --git a/htroot/api/ymarks/get_ymark.json b/htroot/api/ymarks/get_ymark.json index 660d63503..0328725bb 100644 --- a/htroot/api/ymarks/get_ymark.json +++ b/htroot/api/ymarks/get_ymark.json @@ -5,10 +5,10 @@ rows: [ #{json}# {id:"#[id]#",cell:[ "#[hash]#", -#(public)#"public"::"private"#(/public)#, +#(public)#"public"::"private"#(/public)#, "

#[title]#

#[desc]#

#[url]#", "

#[tags]#

", -"

#[folders]#

", +"

#[folders]#

", "

#[date_added]#

"]}#[comma]# #{/json}# ] diff --git a/htroot/api/ymarks/import_ymark.java b/htroot/api/ymarks/import_ymark.java index 407c14a92..00a13f60a 100644 --- a/htroot/api/ymarks/import_ymark.java +++ b/htroot/api/ymarks/import_ymark.java @@ -2,21 +2,21 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; +import java.util.concurrent.ArrayBlockingQueue; + import net.yacy.cora.document.UTF8; import net.yacy.cora.protocol.RequestHeader; -import net.yacy.document.Parser.Failure; import net.yacy.document.content.SurrogateReader; -import net.yacy.kelondro.data.meta.DigestURI; import net.yacy.kelondro.index.RowSpaceExceededException; import net.yacy.kelondro.logging.Log; import org.xml.sax.SAXException; import de.anomic.data.UserDB; +import de.anomic.data.ymark.YMarkAutoTagger; import de.anomic.data.ymark.YMarkEntry; import de.anomic.data.ymark.YMarkHTMLImporter; import de.anomic.data.ymark.YMarkJSONImporter; -import de.anomic.data.ymark.YMarkMetadata; import de.anomic.data.ymark.YMarkTables; import de.anomic.data.ymark.YMarkXBELImporter; import de.anomic.search.Switchboard; @@ -32,6 +32,8 @@ public class import_ymark { final UserDB.Entry user = sb.userDB.getUser(header); final boolean isAdmin = (sb.verifyAuthentication(header, true)); final boolean isAuthUser = user!= null && user.hasRight(UserDB.AccessRight.BOOKMARK_RIGHT); + final int queueSize = 20; + Thread t; YMarkEntry bmk; String root = YMarkEntry.FOLDERS_IMPORTED; @@ -39,6 +41,24 @@ public class import_ymark { if(isAdmin || isAuthUser) { String bmk_user = (isAuthUser ? user.getUserName() : YMarkTables.USER_ADMIN); + final ArrayBlockingQueue autoTaggingQueue = new ArrayBlockingQueue(2*queueSize); + boolean autotag = false; + boolean merge = false; + boolean empty = false; + + if(post.containsKey("autotag") && !post.get("autotag", "off").equals("off")) { + if(post.get("autotag").equals("merge")) { + autotag = true; + merge = true; + } + if(post.get("autotag").equals("empty")) { + autotag = true; + empty = true; + } + t = new Thread(new YMarkAutoTagger(autoTaggingQueue, sb.loader, sb.tables.bookmarks, bmk_user, merge),"YMarks - autoTagger"); + t.start(); + } + if(isAdmin && post.containsKey("table") && post.get("table").length() > 0) { bmk_user = post.get("table").substring(0, post.get("table").indexOf('_')); } @@ -54,7 +74,7 @@ public class import_ymark { if(post.get("importer").equals("surro") && stream != null) { SurrogateReader surrogateReader; try { - surrogateReader = new SurrogateReader(stream, 10); + surrogateReader = new SurrogateReader(stream, queueSize); } catch (IOException e) { //TODO: display an error message Log.logException(e); @@ -64,7 +84,7 @@ public class import_ymark { t = new Thread(surrogateReader, "YMarks - Surrogate Reader"); t.start(); while ((bmk = new YMarkEntry(surrogateReader.take())) != YMarkEntry.POISON) { - putBookmark(sb, bmk_user, bmk); + putBookmark(sb.tables.bookmarks, bmk_user, bmk, autoTaggingQueue, autotag, empty); } prop.put("result", "1"); } else { @@ -78,18 +98,18 @@ public class import_ymark { return prop; } if(post.get("importer").equals("html") && reader != null) { - final YMarkHTMLImporter htmlImporter = new YMarkHTMLImporter(reader, 10, root); + final YMarkHTMLImporter htmlImporter = new YMarkHTMLImporter(reader, queueSize, root); t = new Thread(htmlImporter, "YMarks - HTML Importer"); t.start(); while ((bmk = htmlImporter.take()) != YMarkEntry.POISON) { - putBookmark(sb, bmk_user, bmk); + putBookmark(sb.tables.bookmarks, bmk_user, bmk, autoTaggingQueue, autotag, empty); } prop.put("result", "1"); } else if(post.get("importer").equals("xbel") && reader != null) { final YMarkXBELImporter xbelImporter; try { //TODO: make RootFold - xbelImporter = new YMarkXBELImporter(reader, 10, root); + xbelImporter = new YMarkXBELImporter(reader, queueSize, root); } catch (SAXException e) { //TODO: display an error message Log.logException(e); @@ -99,41 +119,56 @@ public class import_ymark { t = new Thread(xbelImporter, "YMarks - XBEL Importer"); t.start(); while ((bmk = xbelImporter.take()) != YMarkEntry.POISON) { - putBookmark(sb, bmk_user, bmk); + putBookmark(sb.tables.bookmarks, bmk_user, bmk, autoTaggingQueue, autotag, empty); } prop.put("result", "1"); } else if(post.get("importer").equals("json") && reader != null) { YMarkJSONImporter jsonImporter; - jsonImporter = new YMarkJSONImporter(reader, 10, root); + jsonImporter = new YMarkJSONImporter(reader, queueSize, root); t = new Thread(jsonImporter, "YMarks - JSON Importer"); t.start(); while ((bmk = jsonImporter.take()) != YMarkEntry.POISON) { - putBookmark(sb, bmk_user, bmk); + putBookmark(sb.tables.bookmarks, bmk_user, bmk, autoTaggingQueue, autotag, empty); } prop.put("result", "1"); } - } + } } + if(post.containsKey("autotag") && !post.get("autotag", "off").equals("off")) { + try { + autoTaggingQueue.put(YMarkAutoTagger.POISON); + Log.logInfo(YMarkTables.BOOKMARKS_LOG, "Importer inserted poison pill in autoTagging queue"); + } catch (InterruptedException e) { + Log.logException(e); + } + } } else { prop.put(YMarkTables.USER_AUTHENTICATE,YMarkTables.USER_AUTHENTICATE_MSG); - } + } // return rewrite properties return prop; } - public static void putBookmark(final Switchboard sb, final String bmk_user, final YMarkEntry bmk) { + public static void putBookmark(final YMarkTables ymarks, final String bmk_user, final YMarkEntry bmk, + final ArrayBlockingQueue autoTaggingQueue, final boolean autotag, final boolean empty) { try { - if(!bmk.containsKey(YMarkEntry.BOOKMARK.TAGS.key()) || bmk.get(YMarkEntry.BOOKMARK.TAGS.key()).equals(YMarkEntry.BOOKMARK.TAGS.deflt())) { - final YMarkMetadata meta = new YMarkMetadata(new DigestURI(bmk.get(YMarkEntry.BOOKMARK.URL.key()))); - meta.loadDocument(sb.loader); - bmk.put(YMarkEntry.BOOKMARK.TAGS.key(), meta.autoTag(3)); + String url = bmk.get(YMarkEntry.BOOKMARK.URL.key()); + // other protocols could cause problems + if(url.startsWith("http")) { + ymarks.addBookmark(bmk_user, bmk, true, true); + if(autotag) { + if(!empty) { + autoTaggingQueue.put(url); + } else if(!bmk.containsKey(YMarkEntry.BOOKMARK.TAGS.key()) || bmk.get(YMarkEntry.BOOKMARK.TAGS.key()).equals(YMarkEntry.BOOKMARK.TAGS.deflt())) { + autoTaggingQueue.put(url); + } + } } - sb.tables.bookmarks.addBookmark(bmk_user, bmk, true); } catch (IOException e) { - Log.logWarning(YMarkTables.BOOKMARKS_LOG.toString(), "Importer - IOException for URL: "+bmk.get(YMarkEntry.BOOKMARK.URL.key())); + Log.logException(e); } catch (RowSpaceExceededException e) { Log.logException(e); - } catch (Failure e) { + } catch (InterruptedException e) { Log.logException(e); } } diff --git a/htroot/api/ymarks/test_import.html b/htroot/api/ymarks/test_import.html index a62c41baf..8ec33f865 100644 --- a/htroot/api/ymarks/test_import.html +++ b/htroot/api/ymarks/test_import.html @@ -29,6 +29,20 @@ Surrogate Reader
+
+ +
+
+ +
+
+
+ +
+
+ +
+
@@ -37,10 +51,16 @@
- +
- + Off +
+ Only for empty tags +
+ Overwriting existing tags +
+ Merging with existing tags
diff --git a/htroot/yacy/ui/sidebar/sidebar_2.html b/htroot/yacy/ui/sidebar/sidebar_2.html index 8ad1354b9..237bc797f 100644 --- a/htroot/yacy/ui/sidebar/sidebar_2.html +++ b/htroot/yacy/ui/sidebar/sidebar_2.html @@ -21,7 +21,7 @@ $("#sidebar-2-1").toggleClass("ui.loading"); $.ajax({ type: "POST", - url: "/api/bookmarks/tags/getTag.xml?top=25&sort=alpha", + url: "/api/ymarks/get_tags.xml?top=25&sort=alpha", dataType: "xml", cache: false, success: function(xml) { diff --git a/source/de/anomic/data/ymark/TablesRowComparator.java b/source/de/anomic/data/ymark/TablesRowComparator.java index 67daeea6a..fe4a8f829 100644 --- a/source/de/anomic/data/ymark/TablesRowComparator.java +++ b/source/de/anomic/data/ymark/TablesRowComparator.java @@ -15,7 +15,6 @@ public class TablesRowComparator implements Comparator { this.sortname = sortname; } - @Override public int compare(Tables.Row row0, Tables.Row row1) { if(row0 != null && row1 != null) { if(row0.containsKey(this.sortname) && row1.containsKey(this.sortname)) { diff --git a/source/de/anomic/data/ymark/YMarkAutoTagger.java b/source/de/anomic/data/ymark/YMarkAutoTagger.java new file mode 100644 index 000000000..1e19b2625 --- /dev/null +++ b/source/de/anomic/data/ymark/YMarkAutoTagger.java @@ -0,0 +1,192 @@ +package de.anomic.data.ymark; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.ArrayBlockingQueue; + +import net.yacy.cora.document.UTF8; +import net.yacy.document.Condenser; +import net.yacy.document.Document; +import net.yacy.document.LibraryProvider; +import net.yacy.document.WordTokenizer; +import net.yacy.document.Parser.Failure; +import net.yacy.kelondro.data.meta.DigestURI; +import net.yacy.kelondro.data.word.Word; +import net.yacy.kelondro.index.RowSpaceExceededException; +import net.yacy.kelondro.logging.Log; +import net.yacy.repository.LoaderDispatcher; +import de.anomic.crawler.CrawlProfile; +import de.anomic.crawler.retrieval.Response; + +public class YMarkAutoTagger implements Runnable, Thread.UncaughtExceptionHandler { + + public final static String SPACE = " "; + public final static String POISON = ""; + + private final ArrayBlockingQueue bmkQueue; + private final YMarkTables ymarks; + private final String bmk_user; + private final LoaderDispatcher loader; + + private boolean merge; + + public YMarkAutoTagger(final ArrayBlockingQueue bmkQueue, final LoaderDispatcher loader, final YMarkTables ymarks, final String bmk_user, final boolean merge) { + this.bmkQueue = bmkQueue; + this.ymarks = ymarks; + this.bmk_user = bmk_user; + this.loader = loader; + this.merge = merge; + } + + public YMarkAutoTagger(final LoaderDispatcher loader, final YMarkTables ymarks, final String bmk_user) { + this.bmkQueue = new ArrayBlockingQueue(1); + this.ymarks = ymarks; + this.bmk_user = bmk_user; + this.loader = loader; + this.merge = true; + } + + private Document loadDocument(final String url) { + DigestURI uri; + Response response; + try { + uri = new DigestURI(url); + } catch (MalformedURLException e) { + Log.logWarning(YMarkTables.BOOKMARKS_LOG, "loadDocument failed due to malformed url: "+url); + return null; + } + try { + response = loader.load(loader.request(uri, true, false), CrawlProfile.CacheStrategy.IFEXIST, Long.MAX_VALUE, true); + } catch (IOException e) { + Log.logWarning(YMarkTables.BOOKMARKS_LOG, "loadDocument failed due to IOException for url: "+url); + return null; + } + try { + return Document.mergeDocuments(response.url(), response.getMimeType(), response.parse()); + } catch (Failure e) { + Log.logWarning(YMarkTables.BOOKMARKS_LOG, "loadDocument failed due to a parser failure for url: "+url); + return null; + } + } + + public String autoTag(final String url, final int max, final TreeMap tags) { + final Document document = loadDocument(url); + final TreeSet topwords = new TreeSet(); + // final TreeMap pairs = new TreeMap(); + + String token; + // StringBuilder pair = new StringBuilder(64); + + if(document != null) { + //get words from document + final Map words = new Condenser(document, true, true, LibraryProvider.dymLib).words(); + + // generate potential tags from document title, description and subject + final int bufferSize = document.dc_title().length() + document.dc_description().length() + document.dc_subject(' ').length() + 32; + final StringBuilder buffer = new StringBuilder(bufferSize); + buffer.append(document.dc_title()); + buffer.append(document.dc_description()); + buffer.append(document.dc_subject(' ')); + final Enumeration tokens = new WordTokenizer(new ByteArrayInputStream(UTF8.getBytes(buffer.toString())), LibraryProvider.dymLib); + + int count = 0; + + // loop through potential tag and rank them + while(tokens.hasMoreElements()) { + count = 0; + token = tokens.nextElement(); + + /* + pair.delete(0, pair.indexOf(SPACE)+1); + if(pair.length() > 1) + pair.append(SPACE); + pair.append(token); + + if(pair.indexOf(SPACE) > 1 && pairs.containsKey(pair.toString())) { + pairs.get(pair.toString()).inc(); + } else { + pairs.put(pair.toString(), new YMarkTag(pair.toString())); + } + */ + + // check if the token appears in the text + if (words.containsKey(token)) { + Word word = words.get(token); + // token appears in text and matches an existing bookmark tag + if (tags.containsKey(token)) { + count = word.occurrences() * tags.get(token).size() * 100; + } + // token appears in text and has more than 3 characters + if (token.length()>3) { + count = word.occurrences() * 100; + } + topwords.add(new YMarkTag(token, count)); + } + } + count = 0; + buffer.setLength(0); + for(YMarkTag tag : topwords) { + if(count < max) { + if(tag.size() > 100) { + buffer.append(tag.name()); + buffer.append(YMarkUtil.TAGS_SEPARATOR); + count++; + } + } else { + break; + } + } + String clean = YMarkUtil.cleanTagsString(buffer.toString()); + return clean; + } + return new String(); + } + + public void run() { + Log.logInfo(YMarkTables.BOOKMARKS_LOG, "autoTagger run()"); + Thread.currentThread().setUncaughtExceptionHandler(this); + String url = null; + String tagString; + Iterator tit; + try { + final TreeMap tags = this.ymarks.getTags(bmk_user); + Log.logInfo(YMarkTables.BOOKMARKS_LOG, "autoTagger queue size: "+bmkQueue.size()); + while((url = bmkQueue.take()) != POISON) { + tagString = this.autoTag(url, 5, tags); + + // update tags + this.ymarks.addTags(this.bmk_user, url, tagString, this.merge); + + // update tags + tit = YMarkUtil.keysStringToSet(tagString).iterator(); + while(tit.hasNext()) { + final String tag = tit.next(); + if(tags.containsKey(tag)) { + tags.get(tag).inc(); + } else { + tags.put(tag, new YMarkTag(tag)); + } + } + } + Log.logInfo(YMarkTables.BOOKMARKS_LOG, "autoTagger has been poisoned"); + } catch (InterruptedException e) { + Log.logException(e); + } catch (IOException e) { + Log.logWarning(YMarkTables.BOOKMARKS_LOG.toString(), "autoTagger - IOException for URL: "+url); + } catch (RowSpaceExceededException e) { + Log.logException(e); + } finally { + } + } + + public void uncaughtException(Thread t, Throwable e) { + Log.logWarning(YMarkTables.BOOKMARKS_LOG, "I caught an uncaughtException in thread "+t.getName()); + Log.logException(e); + } +} diff --git a/source/de/anomic/data/ymark/YMarkEntry.java b/source/de/anomic/data/ymark/YMarkEntry.java index c7219da97..e3f083c19 100644 --- a/source/de/anomic/data/ymark/YMarkEntry.java +++ b/source/de/anomic/data/ymark/YMarkEntry.java @@ -96,12 +96,18 @@ public class YMarkEntry extends TreeMap { } public YMarkEntry() { - super(); - setCurrentTimeMillis(BOOKMARK.DATE_ADDED); - setCurrentTimeMillis(BOOKMARK.DATE_MODIFIED); - setDefaults(); + this(true); } + public YMarkEntry(final boolean setDefaults) { + super(); + if(setDefaults) { + setCurrentTimeMillis(BOOKMARK.DATE_ADDED); + setCurrentTimeMillis(BOOKMARK.DATE_MODIFIED); + setDefaults(); + } + } + public YMarkEntry(final DCEntry dc) { for (BOOKMARK b : BOOKMARK.values()) { if(dc.containsKey(b.dc_attrb)) { @@ -122,8 +128,14 @@ public class YMarkEntry extends TreeMap { } private void setCurrentTimeMillis(BOOKMARK b) { - final String date = String.valueOf(System.currentTimeMillis()); - this.put(b.key(), date); + switch(b) { + case DATE_ADDED: + case DATE_MODIFIED: + case DATE_VISITED: + this.put(b.key(), String.valueOf(System.currentTimeMillis())); + default: + break; + } } private void setDefaults() { diff --git a/source/de/anomic/data/ymark/YMarkHTMLImporter.java b/source/de/anomic/data/ymark/YMarkHTMLImporter.java index da9bfec40..191784b54 100644 --- a/source/de/anomic/data/ymark/YMarkHTMLImporter.java +++ b/source/de/anomic/data/ymark/YMarkHTMLImporter.java @@ -65,7 +65,7 @@ public class YMarkHTMLImporter extends HTMLEditorKit.ParserCallback implements R this.bookmarks = new ArrayBlockingQueue(queueSize); this.bmk_file = bmk_file; this.RootFolder = root; - this.folderstring = new StringBuilder(YMarkTables.FOLDER_BUFFER_SIZE); + this.folderstring = new StringBuilder(YMarkTables.BUFFER_LENGTH); this.folderstring.append(this.RootFolder); this.bmk = new YMarkEntry(); diff --git a/source/de/anomic/data/ymark/YMarkJSONImporter.java b/source/de/anomic/data/ymark/YMarkJSONImporter.java index 8322f3ed4..23c7468e1 100644 --- a/source/de/anomic/data/ymark/YMarkJSONImporter.java +++ b/source/de/anomic/data/ymark/YMarkJSONImporter.java @@ -43,7 +43,7 @@ public class YMarkJSONImporter implements Runnable, ContentHandler{ this.bookmarks = new ArrayBlockingQueue(queueSize); this.bmk_file = bmk_file; this.RootFolder = root; - this.folderstring = new StringBuilder(YMarkTables.FOLDER_BUFFER_SIZE); + this.folderstring = new StringBuilder(YMarkTables.BUFFER_LENGTH); this.folderstring.append(this.RootFolder); this.bmk = new YMarkEntry(); diff --git a/source/de/anomic/data/ymark/YMarkMetadata.java b/source/de/anomic/data/ymark/YMarkMetadata.java index 12eb43f80..74b7fcac3 100644 --- a/source/de/anomic/data/ymark/YMarkMetadata.java +++ b/source/de/anomic/data/ymark/YMarkMetadata.java @@ -26,12 +26,9 @@ package de.anomic.data.ymark; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.MalformedURLException; -import java.util.ArrayList; import java.util.EnumMap; -import java.util.Enumeration; import java.util.Map; import java.util.TreeMap; @@ -40,7 +37,6 @@ import net.yacy.cora.document.UTF8; import net.yacy.document.Condenser; import net.yacy.document.Document; import net.yacy.document.LibraryProvider; -import net.yacy.document.WordTokenizer; import net.yacy.document.Parser.Failure; import net.yacy.kelondro.data.meta.DigestURI; import net.yacy.kelondro.data.meta.URIMetadataRow; @@ -141,50 +137,10 @@ public class YMarkMetadata { metadata.put(METADATA.LANGUAGE, this.document.dc_language()); metadata.put(METADATA.CHARSET, this.document.getCharset()); // metadata.put(METADATA.SIZE, String.valueOf(document.getTextLength())); - metadata.put(METADATA.AUTOTAG, this.autoTag(5)); } return metadata; } - public String autoTag(final int count) { - final StringBuilder buffer = new StringBuilder(); - final Map words; - if(this.document != null) { - words = new Condenser(this.document, true, true, LibraryProvider.dymLib).words(); - buffer.append(this.document.dc_title()); - buffer.append(this.document.dc_description()); - buffer.append(this.document.dc_subject(' ')); - final Enumeration tokens = new WordTokenizer(new ByteArrayInputStream(UTF8.getBytes(buffer.toString())), LibraryProvider.dymLib); - while(tokens.hasMoreElements()) { - int max = 1; - String token = tokens.nextElement(); - Word word = words.get(token); - if (words.containsKey(token)) { - /* - if (this.worktables.has(TABLES.TAGS.tablename(bmk_user), YMarkUtil.getKeyId(token))) { - max = word.occurrences() * 1000; - } else - */ - if (token.length()>3) { - max = word.occurrences() * 100; - } - for(int i=0; i topwords = new ArrayList(sortWordCounts(words).descendingKeySet()); - for(int i=0; i 100) { - buffer.append(topwords.get(i)); - buffer.append(YMarkUtil.TAGS_SEPARATOR); - } - } - } - return YMarkUtil.cleanTagsString(buffer.toString()); - } - public TreeMap getWordCounts() { if (this.document != null) { return sortWordCounts(new Condenser(this.document, true, true, LibraryProvider.dymLib).words()); diff --git a/source/de/anomic/data/ymark/YMarkTables.java b/source/de/anomic/data/ymark/YMarkTables.java index d70c49979..9aa7f2eb3 100644 --- a/source/de/anomic/data/ymark/YMarkTables.java +++ b/source/de/anomic/data/ymark/YMarkTables.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.SortedSet; +import java.util.TreeMap; import java.util.TreeSet; import java.util.regex.Pattern; @@ -75,8 +76,7 @@ public class YMarkTables { } } - public final static String FOLDERS_ROOT = "/"; - public final static int FOLDER_BUFFER_SIZE = 100; + public final static String FOLDERS_ROOT = "/"; public final static String BOOKMARKS_LOG = "BOOKMARKS"; public final static String USER_ADMIN = "admin"; public final static String USER_AUTHENTICATE = "AUTHENTICATE"; @@ -91,12 +91,12 @@ public class YMarkTables { public final static String p7 = "/.*)"; public final static String p8 = "(?:,|$)"; + public final static int BUFFER_LENGTH = 256; + private final WorkTables worktables; - private final StringBuffer patternBuilder; public YMarkTables(final Tables wt) { this.worktables = (WorkTables)wt; - this.patternBuilder = new StringBuffer(512); } public void deleteBookmark(final String bmk_user, final byte[] urlHash) throws IOException, RowSpaceExceededException { @@ -112,19 +112,48 @@ public class YMarkTables { this.deleteBookmark(bmk_user, YMarkUtil.getBookmarkId(url)); } + public TreeMap getTags(final Iterator rowIterator) throws IOException { + final TreeMap tags = new TreeMap(); + Tables.Row bmk_row = null; + Iterator tit = null; + String tag; + while(rowIterator.hasNext()) { + bmk_row = rowIterator.next(); + if(bmk_row.containsKey(YMarkEntry.BOOKMARK.TAGS.key())) { + tit = YMarkUtil.keysStringToSet(bmk_row.get(YMarkEntry.BOOKMARK.TAGS.key(), YMarkEntry.BOOKMARK.TAGS.deflt())).iterator(); + while(tit.hasNext()) { + tag = tit.next(); + if(tags.containsKey(tag)) { + tags.get(tag).inc(); + } else { + tags.put(tag, new YMarkTag(tag)); + } + } + } + } + return tags; + } + + public TreeMap getTags(final String bmk_user) throws IOException { + final String bmk_table = TABLES.BOOKMARKS.tablename(bmk_user); + final TreeMap tags = getTags(this.worktables.iterator(bmk_table)); + return tags; + } + + public TreeSet getFolders(final String bmk_user, final String root) throws IOException { final String bmk_table = TABLES.BOOKMARKS.tablename(bmk_user); - this.patternBuilder.setLength(0); - this.patternBuilder.append(p1); - this.patternBuilder.append('('); - this.patternBuilder.append(root); - this.patternBuilder.append(p7); - this.patternBuilder.append(p8); - - final Pattern r = Pattern.compile(this.patternBuilder.toString()); - final Iterator bit = this.worktables.iterator(bmk_table, YMarkEntry.BOOKMARK.FOLDERS.key(), r); final TreeSet folders = new TreeSet(); final StringBuilder path = new StringBuilder(200); + final StringBuffer patternBuilder = new StringBuffer(BUFFER_LENGTH); + patternBuilder.setLength(0); + patternBuilder.append(p1); + patternBuilder.append('('); + patternBuilder.append(root); + patternBuilder.append(p7); + patternBuilder.append(p8); + final Pattern r = Pattern.compile(patternBuilder.toString()); + final Iterator bit = this.worktables.iterator(bmk_table, YMarkEntry.BOOKMARK.FOLDERS.key(), r); Tables.Row bmk_row = null; while(bit.hasNext()) { @@ -152,38 +181,40 @@ public class YMarkTables { public Iterator getBookmarksByFolder(final String bmk_user, final String folder) throws IOException { final String bmk_table = TABLES.BOOKMARKS.tablename(bmk_user); - this.patternBuilder.setLength(0); - this.patternBuilder.append(p1); - this.patternBuilder.append('('); - this.patternBuilder.append(p2); - this.patternBuilder.append(folder); - this.patternBuilder.append(p3); - this.patternBuilder.append(')'); - this.patternBuilder.append(p4); - final Pattern p = Pattern.compile(this.patternBuilder.toString()); + final StringBuffer patternBuilder = new StringBuffer(BUFFER_LENGTH); + patternBuilder.setLength(0); + patternBuilder.append(p1); + patternBuilder.append('('); + patternBuilder.append(p2); + patternBuilder.append(folder); + patternBuilder.append(p3); + patternBuilder.append(')'); + patternBuilder.append(p4); + final Pattern p = Pattern.compile(patternBuilder.toString()); return this.worktables.iterator(bmk_table, YMarkEntry.BOOKMARK.FOLDERS.key(), p); } public Iterator getBookmarksByTag(final String bmk_user, final String[] tagArray) throws IOException { final String bmk_table = TABLES.BOOKMARKS.tablename(bmk_user); - this.patternBuilder.setLength(0); - this.patternBuilder.append(p1); - this.patternBuilder.append(p5); + final StringBuffer patternBuilder = new StringBuffer(BUFFER_LENGTH); + patternBuilder.setLength(0); + patternBuilder.append(p1); + patternBuilder.append(p5); for (final String tag : tagArray) { - this.patternBuilder.append(p2); - this.patternBuilder.append(tag); - this.patternBuilder.append(p3); - this.patternBuilder.append('|'); + patternBuilder.append(p2); + patternBuilder.append(tag); + patternBuilder.append(p3); + patternBuilder.append('|'); } - this.patternBuilder.deleteCharAt(this.patternBuilder.length()-1); - this.patternBuilder.append(p6); - this.patternBuilder.append(tagArray.length); - this.patternBuilder.append('}'); - final Pattern p = Pattern.compile(this.patternBuilder.toString()); + patternBuilder.deleteCharAt(patternBuilder.length()-1); + patternBuilder.append(p6); + patternBuilder.append(tagArray.length); + patternBuilder.append('}'); + final Pattern p = Pattern.compile(patternBuilder.toString()); return this.worktables.iterator(bmk_table, YMarkEntry.BOOKMARK.TAGS.key(), p); } - public SortedSet orderBy(final Iterator rowIterator, final String sortname, final String sortorder) { + public SortedSet orderBookmarksBy(final Iterator rowIterator, final String sortname, final String sortorder) { TreeSet sortTree = new TreeSet(new TablesRowComparator(sortname)); Row row; while (rowIterator.hasNext()) { @@ -196,7 +227,17 @@ public class YMarkTables { return sortTree; } - public void addBookmark(final String bmk_user, final YMarkEntry bmk, final boolean importer) throws IOException, RowSpaceExceededException { + public void addTags(final String bmk_user, final String url, final String tagString, final boolean merge) throws IOException, RowSpaceExceededException { + if(!tagString.isEmpty()) { + // do not set defaults as we only want to update tags + final YMarkEntry bmk = new YMarkEntry(false); + bmk.put(YMarkEntry.BOOKMARK.URL.key(), url); + bmk.put(YMarkEntry.BOOKMARK.TAGS.key(), YMarkUtil.cleanTagsString(tagString)); + this.addBookmark(bmk_user, bmk, merge, true); + } + } + + public void addBookmark(final String bmk_user, final YMarkEntry bmk, final boolean mergeTags, final boolean mergeFolders) throws IOException, RowSpaceExceededException { final String bmk_table = TABLES.BOOKMARKS.tablename(bmk_user); final String date = String.valueOf(System.currentTimeMillis()); final byte[] urlHash = YMarkUtil.getBookmarkId(bmk.get(YMarkEntry.BOOKMARK.URL.key())); @@ -208,10 +249,11 @@ public class YMarkTables { // create and insert new entry this.worktables.insert(bmk_table, urlHash, bmk.getData()); } else { - // modify and update existing entry + // modify and update existing entry HashSet oldSet; HashSet newSet; - for (YMarkEntry.BOOKMARK b : YMarkEntry.BOOKMARK.values()) { + + for (YMarkEntry.BOOKMARK b : YMarkEntry.BOOKMARK.values()) { switch(b) { case DATE_ADDED: if(!bmk_row.containsKey(b.key())) @@ -224,15 +266,15 @@ public class YMarkTables { oldSet = YMarkUtil.keysStringToSet(bmk_row.get(b.key(),b.deflt())); if(bmk.containsKey(b.key())) { newSet = YMarkUtil.keysStringToSet(bmk.get(b.key())); - if(importer) { + if(mergeTags) { newSet.addAll(oldSet); + if(newSet.size() > 1 && newSet.contains(YMarkEntry.BOOKMARK.TAGS.deflt())) + newSet.remove(YMarkEntry.BOOKMARK.TAGS.deflt()); bmk_row.put(b.key(), YMarkUtil.keySetToString(newSet)); - oldSet.clear(); } else { bmk_row.put(b.key(), bmk.get(b.key())); } } else { - newSet = new HashSet(); bmk_row.put(b.key(), bmk_row.get(b.key(), b.deflt())); } break; @@ -240,15 +282,15 @@ public class YMarkTables { oldSet = YMarkUtil.keysStringToSet(bmk_row.get(b.key(),b.deflt())); if(bmk.containsKey(b.key())) { newSet = YMarkUtil.keysStringToSet(bmk.get(b.key())); - if(importer) { + if(mergeFolders) { newSet.addAll(oldSet); + if(newSet.size() > 1 && newSet.contains(YMarkEntry.BOOKMARK.FOLDERS.deflt())) + newSet.remove(YMarkEntry.BOOKMARK.FOLDERS.deflt()); bmk_row.put(b.key(), YMarkUtil.keySetToString(newSet)); - oldSet.clear(); } else { bmk_row.put(b.key(), bmk.get(b.key())); } } else { - newSet = new HashSet(); bmk_row.put(b.key(), bmk_row.get(b.key(), b.deflt())); } break; diff --git a/source/de/anomic/data/ymark/YMarkTag.java b/source/de/anomic/data/ymark/YMarkTag.java new file mode 100644 index 000000000..72cc4756b --- /dev/null +++ b/source/de/anomic/data/ymark/YMarkTag.java @@ -0,0 +1,46 @@ +package de.anomic.data.ymark; + +public class YMarkTag implements Comparable{ + private String name; + private int size; + + public YMarkTag(final String tag) { + this.name = tag.toLowerCase(); + this.size = 1; + } + + public YMarkTag(final String tag, final int size) { + this.name = tag.toLowerCase(); + this.size = size; + } + + public int inc() { + return this.size++; + } + + public int dec() { + if(this.size > 0) + this.size--; + return this.size; + } + + public String name() { + return this.name; + } + + public int size() { + return this.size; + } + + public int compareTo(YMarkTag tag) { + if(this.name.equals(tag.name())) + return 0; + if(tag.size() < this.size) + return -1; + else if(tag.size() > this.size) + return 1; + else + return this.name.compareTo(tag.name()); + } +} + diff --git a/source/de/anomic/data/ymark/YMarkXBELImporter.java b/source/de/anomic/data/ymark/YMarkXBELImporter.java index e2ce7140a..93a6db765 100644 --- a/source/de/anomic/data/ymark/YMarkXBELImporter.java +++ b/source/de/anomic/data/ymark/YMarkXBELImporter.java @@ -53,7 +53,7 @@ public class YMarkXBELImporter extends DefaultHandler implements Runnable { private YMarkEntry bmk; private final XMLReader xmlReader; - // Statics + // Statics public static enum XBEL { NOTHING (""), XBEL ("(queueSize); this.bmk_file = bmk_file; this.RootFolder = root; - this.folderstring = new StringBuilder(YMarkTables.FOLDER_BUFFER_SIZE); + this.folderstring = new StringBuilder(YMarkTables.BUFFER_LENGTH); this.folderstring.append(this.RootFolder); this.bmk = new YMarkEntry(); @@ -123,7 +123,7 @@ public class YMarkXBELImporter extends DefaultHandler implements Runnable { this.bmkRef = new HashMap(); this.aliasRef = new HashSet(); this.buffer = new StringBuilder(); - this.folder = new StringBuilder(YMarkTables.FOLDER_BUFFER_SIZE); + this.folder = new StringBuilder(YMarkTables.BUFFER_LENGTH); this.folder.append(this.RootFolder); } @@ -180,8 +180,8 @@ public class YMarkXBELImporter extends DefaultHandler implements Runnable { } this.bmk.put(YMarkEntry.BOOKMARK.DATE_MODIFIED.key(), date.toString()); UpdateBmkRef(atts.getValue(uri, YMarkEntry.BOOKMARKS_ID), true); - outer_state = XBEL.BOOKMARK; - inner_state = XBEL.NOTHING; + this.outer_state = XBEL.BOOKMARK; + this.inner_state = XBEL.NOTHING; this.parse_value = false; } else if(XBEL.FOLDER.tag().equals(tag)) { this.outer_state = XBEL.FOLDER; @@ -196,9 +196,15 @@ public class YMarkXBELImporter extends DefaultHandler implements Runnable { this.inner_state = XBEL.INFO; this.parse_value = false; } else if (XBEL.METADATA.tag().equals(tag)) { - /* - atts.getValue(uri, "owner"); - */ + // Support for old YaCy BookmarksDB XBEL Metadata (non valid XBEL) + if(this.outer_state == XBEL.BOOKMARK) { + final boolean isMozillaShortcutURL = atts.getValue(uri, "owner").equals("Mozilla") && !atts.getValue(uri, "ShortcutURL").isEmpty(); + final boolean isYacyPublic = atts.getValue(uri, "owner").equals("YaCy") && !atts.getValue(uri, "public").isEmpty(); + if(isMozillaShortcutURL) + this.bmk.put(YMarkEntry.BOOKMARK.TAGS.key(), YMarkUtil.cleanTagsString(atts.getValue(uri, "ShortcutURL"))); + if(isYacyPublic) + this.bmk.put(YMarkEntry.BOOKMARK.PUBLIC.key(), atts.getValue(uri, "public")); + } } else if (XBEL.ALIAS.tag().equals(tag)) { final String r = atts.getValue(uri, YMarkEntry.BOOKMARKS_REF); UpdateBmkRef(r, false); @@ -242,25 +248,16 @@ public class YMarkXBELImporter extends DefaultHandler implements Runnable { public void characters(final char ch[], final int start, final int length) { if (parse_value) { - buffer.append(ch, start, length); - for (int i = 0; i < buffer.length()-1; i++) { - if(buffer.charAt(i) == '\n' | buffer.charAt(i) == '\t') { - buffer.deleteCharAt(i); - i--; - } - } + buffer.append(ch, start, length); switch(outer_state) { case BOOKMARK: switch(inner_state) { case DESC: - this.bmk.put(YMarkEntry.BOOKMARK.DESC.key(), buffer.toString()); + this.bmk.put(YMarkEntry.BOOKMARK.DESC.key(), buffer.toString().trim()); break; case TITLE: - this.bmk.put(YMarkEntry.BOOKMARK.TITLE.key(), buffer.toString()); + this.bmk.put(YMarkEntry.BOOKMARK.TITLE.key(), buffer.toString().trim()); break; - case METADATA: - // TODO: handle xbel bookmark metadata - break; default: break; } @@ -273,9 +270,6 @@ public class YMarkXBELImporter extends DefaultHandler implements Runnable { this.folder.append(YMarkUtil.FOLDERS_SEPARATOR); this.folder.append(this.buffer); break; - case METADATA: - // TODO: handle xbel folder metadata - break; default: break; }