more updates to ymarks

- working xbel import/export
- exported xbel includes yacy specific metadata but still validates against PUBLIC DTD


git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@7315 6c8d7289-2bf4-0310-a012-ef5d649a1542
pull/1/head
apfelmaennchen 14 years ago
parent d62e449a11
commit 25339f93c7

@ -122,10 +122,13 @@ public class get_treeview {
while(it.hasNext()) { while(it.hasNext()) {
final String key = it.next(); final String key = it.next();
if(key.startsWith("date")) { if(key.startsWith("date")) {
final String date = DateFormatter.formatISO8601(new Date(Long.parseLong(new String(bmk_row.get(key))))); final String d = new String(bmk_row.get(key));
prop.put("folders_"+count+"_foldername","<small><b>"+key+":</b> " + date + "</small>"); if(!d.isEmpty()) {
putProp(count, "date"); final String date = DateFormatter.formatISO8601(new Date(Long.parseLong(d)));
count++; prop.put("folders_"+count+"_foldername","<small><b>"+key+":</b> " + date + "</small>");
putProp(count, "date");
count++;
}
} else { } else {
final String value = new String(bmk_row.get(key)); final String value = new String(bmk_row.get(key));
prop.put("folders_"+count+"_foldername","<small><b>"+key+":</b> " + value + "</small>"); prop.put("folders_"+count+"_foldername","<small><b>"+key+":</b> " + value + "</small>");

@ -1,4 +1,5 @@
import java.io.IOException; import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import net.yacy.cora.protocol.RequestHeader; import net.yacy.cora.protocol.RequestHeader;
@ -6,8 +7,8 @@ import net.yacy.document.parser.html.CharacterCoding;
import net.yacy.kelondro.blob.Tables; import net.yacy.kelondro.blob.Tables;
import net.yacy.kelondro.index.RowSpaceExceededException; import net.yacy.kelondro.index.RowSpaceExceededException;
import net.yacy.kelondro.logging.Log; import net.yacy.kelondro.logging.Log;
import de.anomic.data.YMarkIndex;
import de.anomic.data.YMarkTables; import de.anomic.data.YMarkTables;
import de.anomic.data.YMarksXBELImporter;
import de.anomic.data.userDB; import de.anomic.data.userDB;
import de.anomic.search.Switchboard; import de.anomic.search.Switchboard;
import de.anomic.server.serverObjects; import de.anomic.server.serverObjects;
@ -16,24 +17,24 @@ import de.anomic.server.serverSwitch;
public class get_xbel { public class get_xbel {
public static final String ROOT = "root"; public static final String ROOT = "root";
public static final String SOURCE = "source"; public static final String SOURCE = "source";
static Switchboard sb;
static serverObjects prop;
static String bmk_user;
public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) { public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
sb = (Switchboard) env; final Switchboard sb = (Switchboard) env;
prop = new serverObjects(); final serverObjects prop = new serverObjects();
final userDB.Entry user = sb.userDB.getUser(header); final HashSet<String> alias = new HashSet<String>();
final StringBuilder buffer = new StringBuilder(250);
final userDB.Entry user = sb.userDB.getUser(header);
final boolean isAdmin = (sb.verifyAuthentication(header, true)); final boolean isAdmin = (sb.verifyAuthentication(header, true));
final boolean isAuthUser = user!= null && user.hasRight(userDB.Entry.BOOKMARK_RIGHT); final boolean isAuthUser = user!= null && user.hasRight(userDB.Entry.BOOKMARK_RIGHT);
final String bmk_user;
if(isAdmin || isAuthUser) { if(isAdmin || isAuthUser) {
bmk_user = (isAuthUser ? user.getUserName() : YMarkTables.USER_ADMIN); bmk_user = (isAuthUser ? user.getUserName() : YMarkTables.USER_ADMIN);
String root = YMarkTables.FOLDERS_ROOT; String root = YMarkTables.FOLDERS_ROOT;
String[] foldername = null; String[] foldername = null;
// TODO: better handling of query
if (post != null){ if (post != null){
if (post.containsKey(ROOT)) { if (post.containsKey(ROOT)) {
if (post.get(ROOT).equals(SOURCE) || post.get(ROOT).equals(YMarkTables.FOLDERS_ROOT)) { if (post.get(ROOT).equals(SOURCE) || post.get(ROOT).equals(YMarkTables.FOLDERS_ROOT)) {
@ -41,38 +42,111 @@ public class get_xbel {
} else if (post.get(ROOT).startsWith(YMarkTables.FOLDERS_ROOT)) { } else if (post.get(ROOT).startsWith(YMarkTables.FOLDERS_ROOT)) {
root = post.get(ROOT); root = post.get(ROOT);
} else { } else {
root = ""; root = "";
// root = YMarkTables.FOLDERS_ROOT + post.get(ROOT);
} }
} }
} else {
root = "";
} }
Iterator<String> it = null; final int root_depth = root.split(YMarkTables.FOLDERS_SEPARATOR).length;
int count = 0; Iterator<String> fit = null;
int n = YMarkIndex.getFolderDepth(root); Iterator<String> bit = null;
int count = 0;
int n = root_depth;
try { try {
it = sb.tables.bookmarks.folders.getFolders(bmk_user, root); fit = sb.tables.bookmarks.folders.getFolders(bmk_user, root);
} catch (IOException e) { } catch (IOException e) {
Log.logException(e); Log.logException(e);
} }
while (it.hasNext()) { Log.logInfo(YMarkTables.BOOKMARKS_LOG, "root: "+root+" root_deph: "+root_depth);
String folder = it.next();
foldername = folder.split(YMarkTables.FOLDERS_SEPARATOR); while (fit.hasNext()) {
Log.logInfo(YMarkTables.BOOKMARKS_LOG, "folder: "+folder+" getFolderDepth(folder): "+YMarkIndex.getFolderDepth(folder)+" n: "+n); String folder = fit.next();
if (count > 0 && YMarkIndex.getFolderDepth(folder) <= n) { foldername = folder.split(YMarkTables.FOLDERS_SEPARATOR);
Log.logInfo(YMarkTables.BOOKMARKS_LOG, "folder: "+folder+" n: "+n+" folder_length: "+foldername.length);
if (n != root_depth && foldername.length <= n) {
prop.put("xbel_"+count+"_elements", "</folder>"); prop.put("xbel_"+count+"_elements", "</folder>");
count++; count++;
} }
if (YMarkIndex.getFolderDepth(folder) >= n) { if (foldername.length >= n) {
n = YMarkIndex.getFolderDepth(folder); n = foldername.length;
prop.put("xbel_"+count+"_elements", "<folder id=\"f:"+new String(YMarkTables.getKeyId(foldername[n]))+"\">"); if(n != root_depth) {
count++; prop.put("xbel_"+count+"_elements", "<folder id=\"f:"+new String(YMarkTables.getKeyId(foldername[n-1]))+"\">");
prop.put("xbel_"+count+"_elements", "<title>" + CharacterCoding.unicode2xml(foldername[n], true) + "</title>"); count++;
count++; prop.put("xbel_"+count+"_elements", "<title>" + CharacterCoding.unicode2xml(foldername[n-1], true) + "</title>");
count++;
}
try { try {
count = putBookmarks(folder, count); bit = sb.tables.bookmarks.folders.getBookmarks(bmk_user, folder).iterator();
Tables.Row bmk_row = null;
String urlHash;
while(bit.hasNext()){
urlHash = new String(bit.next());
if(alias.contains(urlHash)) {
buffer.setLength(0);
buffer.append(YMarksXBELImporter.XBEL.ALIAS.startTag(true));
buffer.append(" ref=\"b:");
buffer.append(urlHash);
buffer.append("\"/>");
prop.put("xbel_"+count+"_elements", buffer.toString());
count++;
} else {
alias.add(urlHash);
bmk_row = sb.tables.select(YMarkTables.TABLES.BOOKMARKS.tablename(bmk_user), urlHash.getBytes());
if(bmk_row != null) {
buffer.setLength(0);
buffer.append(YMarksXBELImporter.XBEL.BOOKMARK.startTag(true));
buffer.append(" id=\"b:");
buffer.append(urlHash);
buffer.append(YMarkTables.BOOKMARK.URL.xbel());
buffer.append(CharacterCoding.unicode2xml(bmk_row.get(YMarkTables.BOOKMARK.URL.key(), YMarkTables.BOOKMARK.URL.deflt()), true));
buffer.append(YMarkTables.BOOKMARK.DATE_ADDED.xbel());
buffer.append(CharacterCoding.unicode2xml(YMarkTables.getISO8601(bmk_row.get(YMarkTables.BOOKMARK.DATE_ADDED.key())), true));
buffer.append(YMarkTables.BOOKMARK.DATE_MODIFIED.xbel());
buffer.append(CharacterCoding.unicode2xml(YMarkTables.getISO8601(bmk_row.get(YMarkTables.BOOKMARK.DATE_MODIFIED.key())), true));
buffer.append(YMarkTables.BOOKMARK.DATE_VISITED.xbel());
buffer.append(CharacterCoding.unicode2xml(YMarkTables.getISO8601(bmk_row.get(YMarkTables.BOOKMARK.DATE_VISITED.key())), true));
buffer.append(YMarkTables.BOOKMARK.TAGS.xbel());
buffer.append(bmk_row.get(YMarkTables.BOOKMARK.TAGS.key(), YMarkTables.BOOKMARK.TAGS.deflt()));
buffer.append(YMarkTables.BOOKMARK.PUBLIC.xbel());
buffer.append(bmk_row.get(YMarkTables.BOOKMARK.PUBLIC.key(), YMarkTables.BOOKMARK.PUBLIC.deflt()));
buffer.append(YMarkTables.BOOKMARK.VISITS.xbel());
buffer.append(bmk_row.get(YMarkTables.BOOKMARK.VISITS.key(), YMarkTables.BOOKMARK.VISITS.deflt()));
buffer.append("\"\n>");
prop.put("xbel_"+count+"_elements", buffer.toString());
count++;
buffer.setLength(0);
buffer.append(YMarksXBELImporter.XBEL.TITLE.startTag(false));
buffer.append(CharacterCoding.unicode2xml(bmk_row.get(YMarkTables.BOOKMARK.TITLE.key(), YMarkTables.BOOKMARK.TITLE.deflt()), true));
buffer.append(YMarksXBELImporter.XBEL.TITLE.endTag(false));
prop.put("xbel_"+count+"_elements", buffer.toString());
count++;
buffer.setLength(0);
buffer.append(YMarksXBELImporter.XBEL.DESC.startTag(false));
buffer.append(CharacterCoding.unicode2xml(bmk_row.get(YMarkTables.BOOKMARK.DESC.key(), YMarkTables.BOOKMARK.DESC.deflt()), true));
buffer.append(YMarksXBELImporter.XBEL.DESC.endTag(false));
prop.put("xbel_"+count+"_elements", buffer.toString());
count++;
prop.put("xbel_"+count+"_elements", YMarksXBELImporter.XBEL.BOOKMARK.endTag(false));
count++;
}
}
}
} catch (IOException e) { } catch (IOException e) {
Log.logException(e); Log.logException(e);
continue; continue;
@ -82,54 +156,20 @@ public class get_xbel {
} }
} }
} }
while(n >= YMarkIndex.getFolderDepth(root)) { while(n > root_depth) {
prop.put("xbel_"+count+"_elements", "</folder>"); prop.put("xbel_"+count+"_elements", YMarksXBELImporter.XBEL.FOLDER.endTag(false));
count++; count++;
n--; n--;
} }
prop.put("user", bmk_user.substring(0,1).toUpperCase() + bmk_user.substring(1));
prop.put("xbel", count); prop.put("xbel", count);
} else { } else {
prop.put(YMarkTables.USER_AUTHENTICATE,YMarkTables.USER_AUTHENTICATE_MSG); prop.put(YMarkTables.USER_AUTHENTICATE,YMarkTables.USER_AUTHENTICATE_MSG);
} }
// return rewrite properties // return rewrite properties
return prop; return prop;
} }
public static int putBookmarks(final String folder, int count) throws IOException, RowSpaceExceededException {
final Iterator<String> bit = sb.tables.bookmarks.folders.getBookmarks(bmk_user, folder).iterator();
Tables.Row bmk_row = null;
String urlHash;
while(bit.hasNext()){
urlHash = new String(bit.next());
bmk_row = sb.tables.select(YMarkTables.TABLES.BOOKMARKS.tablename(bmk_user), urlHash.getBytes());
if(bmk_row != null) {
prop.put("xbel_"+count+"_elements", "<bookmark id=\"b:" + urlHash
+ "\" href=\"" + CharacterCoding.unicode2xml(bmk_row.get(YMarkTables.BOOKMARK.URL.key(), YMarkTables.BOOKMARK.URL.deflt()), true)
+ "\" added=\"" + CharacterCoding.unicode2xml(YMarkTables.getISO8601(bmk_row.get(YMarkTables.BOOKMARK.DATE_ADDED.key())), true)
+ "\" modified=\"" + CharacterCoding.unicode2xml(YMarkTables.getISO8601(bmk_row.get(YMarkTables.BOOKMARK.DATE_MODIFIED.key())), true)
+ "\" visited=\"" + CharacterCoding.unicode2xml(YMarkTables.getISO8601(bmk_row.get(YMarkTables.BOOKMARK.DATE_VISITED.key())), true)
+"\">");
count++;
prop.put("xbel_"+count+"_elements", "<title>"
+ CharacterCoding.unicode2xml(bmk_row.get(YMarkTables.BOOKMARK.TITLE.key(), YMarkTables.BOOKMARK.TITLE.deflt()), true)
+ "</title>");
count++;
prop.put("xbel_"+count+"_elements", "<info>");
count++;
prop.put("xbel_"+count+"_elements", "<metadata owner=\"YaCy\""
+ " tags=\"" + bmk_row.get(YMarkTables.BOOKMARK.TAGS.key(), YMarkTables.BOOKMARK.TAGS.deflt()) +"\""
+ " public=\"" + bmk_row.get(YMarkTables.BOOKMARK.PUBLIC.key(), YMarkTables.BOOKMARK.PUBLIC.deflt()) +"\""
+ "/>");
count++;
prop.put("xbel_"+count+"_elements", "</info>");
count++;
prop.put("xbel_"+count+"_elements", "<desc>"
+ CharacterCoding.unicode2xml(bmk_row.get(YMarkTables.BOOKMARK.DESC.key(), YMarkTables.BOOKMARK.DESC.deflt()), true)
+ "</desc>");
count++;
prop.put("xbel_"+count+"_elements", "</bookmark>");
count++;
}
}
return count;
}
} }

@ -1,8 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xbel PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML" "http://pyxml.sourceforge.net/topics/dtds/xbel-1.0.dtd"> <!DOCTYPE xbel PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML" "http://pyxml.sourceforge.net/topics/dtds/xbel-1.0.dtd"
#(style)#::<?xml-stylesheet type="text/#[type]#" href="#[href]#" ?>#(/style)# [
<xbel> <!ENTITY % local.url.att "yacy:public CDATA #IMPLIED yacy:tags CDATA #IMPLIED yacy:visits CDATA #IMPLIED">
#{xbel}# ]>
#[elements]# <xbel version="1.0" xmlns:yacy="http://www.yacy.net">
#{/xbel}# <title>#[user]# YaCy Bookmarks</title>
<info>
<metadata owner="http://www.yacy.net" />
</info>
#{xbel}#
#[elements]#
#{/xbel}#
</xbel> </xbel>

@ -2,6 +2,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -82,6 +83,21 @@ public class import_ymark {
prop.put("result", "0"); prop.put("result", "0");
return prop; return prop;
} }
}
// update bookmarks with aliases
final Iterator<HashMap<String,String>> it = xbelImporter.getAliases().iterator();
while (it.hasNext()) {
try {
sb.tables.bookmarks.addBookmark(bmk_user, it.next(), true);
} catch (IOException e) {
Log.logWarning(YMarkTables.BOOKMARKS_LOG.toString(), "XBEL Importer - IOException for URL: "+bmk.get(YMarkTables.BOOKMARK.URL.key()));
continue;
} catch (RowSpaceExceededException e) {
//TODO: display an error message
Log.logException(e);
prop.put("result", "0");
return prop;
}
} }
prop.put("result", "1"); prop.put("result", "1");
} }

@ -33,11 +33,16 @@
</li> </li>
<li>get_treeview.[xml | json] <li>get_treeview.[xml | json]
<ul> <ul>
<li><i>root:</i></li> <li><i>root:</i> the folder to display</li>
<li><i>bmtype:</i></li> <li><i>bmtype:</i></li>
</ul> </ul>
</li> </li>
<li>get_xbel</li> <li>get_xml
<ul>
<li><i>root:</i> the root folder to start export from</li>
<li><i>type:</i> xbel | rss | rdf</li>
</ul>
</li>
<li>import_ymark.xml <li>import_ymark.xml
<ul> <ul>
<li><i>bmfile:</i> the bookmark file you want to import <li><i>bmfile:</i> the bookmark file you want to import

@ -4,7 +4,7 @@
<title>YaCy Bookmarks</title> <title>YaCy Bookmarks</title>
</head> </head>
<body> <body>
<form action="/api/ymarks/import_ymark.xml" method="post" enctype="multipart/form-data"> <form action="/api/ymarks/import_ymark.xml" method="post" enctype="multipart/form-data" accept-charset="UTF-8">
<fieldset> <fieldset>
<legend>Import Bookmarks</legend> <legend>Import Bookmarks</legend>
<dl> <dl>

@ -60,14 +60,6 @@ public class YMarkIndex {
return new String(row.get(INDEX.NAME.key(), INDEX.NAME.deflt())); return new String(row.get(INDEX.NAME.key(), INDEX.NAME.deflt()));
} }
public static int getFolderDepth(String folder) {
final int depth = folder.split(YMarkTables.FOLDERS_SEPARATOR).length -1;
if (depth < 0)
return 0;
else
return depth;
}
public Iterator<String> getFolders(final String user, final String root) throws IOException { public Iterator<String> getFolders(final String user, final String root) throws IOException {
final String index_table = user + this.table_basename; final String index_table = user + this.table_basename;
final TreeSet<String> folders = new TreeSet<String>(); final TreeSet<String> folders = new TreeSet<String>();

@ -16,7 +16,6 @@ import net.yacy.kelondro.blob.Tables.Data;
import net.yacy.kelondro.data.meta.DigestURI; import net.yacy.kelondro.data.meta.DigestURI;
import net.yacy.kelondro.data.word.Word; import net.yacy.kelondro.data.word.Word;
import net.yacy.kelondro.index.RowSpaceExceededException; import net.yacy.kelondro.index.RowSpaceExceededException;
import net.yacy.kelondro.logging.Log;
import net.yacy.kelondro.util.DateFormatter; import net.yacy.kelondro.util.DateFormatter;
public class YMarkTables { public class YMarkTables {
@ -57,15 +56,16 @@ public class YMarkTables {
} }
public static enum BOOKMARK { public static enum BOOKMARK {
// key dflt html_attrb xbel_attrb type
URL ("url", "", "href", "href", "link"), URL ("url", "", "href", "href", "link"),
TITLE ("title", "", "", "", "meta"), TITLE ("title", "", "", "", "meta"),
DESC ("desc", "", "", "", "comment"), DESC ("desc", "", "", "", "comment"),
DATE_ADDED ("date_added", "", "add_date", "added", "date"), DATE_ADDED ("date_added", "", "add_date", "added", "date"),
DATE_MODIFIED ("date_modified", "", "last_modified", "modified", "date"), DATE_MODIFIED ("date_modified", "", "last_modified", "modified", "date"),
DATE_VISITED ("date_visited", "", "last_visited", "visited", "date"), DATE_VISITED ("date_visited", "", "last_visited", "visited", "date"),
PUBLIC ("public", "flase", "", "", "lock"), PUBLIC ("public", "flase", "", "yacy:public", "lock"),
TAGS ("tags", "unsorted", "shortcuturl", "", "tag"), TAGS ("tags", "unsorted", "shortcuturl", "yacy:tags", "tag"),
VISITS ("visits", "0", "", "", "stat"), VISITS ("visits", "0", "", "yacy:visits", "stat"),
FOLDERS ("folders", "/unsorted", "", "", "folder"); FOLDERS ("folders", "/unsorted", "", "", "folder");
private String key; private String key;
@ -80,6 +80,8 @@ public class YMarkTables {
lookup.put(b.key(), b); lookup.put(b.key(), b);
} }
private static StringBuilder buffer = new StringBuilder(25);;
private BOOKMARK(String k, String s, String a, String x, String t) { private BOOKMARK(String k, String s, String a, String x, String t) {
this.key = k; this.key = k;
this.dflt = s; this.dflt = s;
@ -105,6 +107,16 @@ public class YMarkTables {
public String xbel_attrb() { public String xbel_attrb() {
return this.xbel_attrb; return this.xbel_attrb;
} }
public String xbel() {
buffer.setLength(0);
buffer.append('"');
buffer.append('\n');
buffer.append(' ');
buffer.append(this.xbel_attrb);
buffer.append('=');
buffer.append('"');
return buffer.toString();
}
public String type() { public String type() {
return this.type; return this.type;
} }
@ -117,7 +129,7 @@ public class YMarkTables {
public final static String FOLDERS_SEPARATOR = "/"; public final static String FOLDERS_SEPARATOR = "/";
public final static String FOLDERS_ROOT = "/"; public final static String FOLDERS_ROOT = "/";
public final static String FOLDERS_UNSORTED = "/unsorted"; public final static String FOLDERS_UNSORTED = "/unsorted";
public final static String FOLDERS_IMPORTED = "/imported"; public final static String FOLDERS_IMPORTED = "";
public static final int FOLDER_BUFFER_SIZE = 100; public static final int FOLDER_BUFFER_SIZE = 100;
public final static String BOOKMARKS_LOG = "BOOKMARKS"; public final static String BOOKMARKS_LOG = "BOOKMARKS";
@ -138,17 +150,22 @@ public class YMarkTables {
} }
public static Date parseISO8601(final String s) throws ParseException { public static Date parseISO8601(final String s) throws ParseException {
if(s == null)
throw new ParseException("parseISO8601 - NPE", 0);
StringBuilder date = new StringBuilder(s); StringBuilder date = new StringBuilder(s);
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"); SimpleDateFormat dateformat;
if(date.charAt(date.length()) == 'Z') { if(s == null || s.isEmpty()) {
date.deleteCharAt(date.length()); throw new ParseException("parseISO8601 - empty string, nothing to parse", 0);
date.append("GMT-00:00"); }
} else { if(s.length()==10)
date.insert(date.length()-6, "GMT"); dateformat = new SimpleDateFormat("yyyy-MM-dd");
} else {
Log.logInfo(YMarkTables.BOOKMARKS_LOG, "ISO8601: "+s+" =? "+dateformat.toString()); dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz");
if(date.charAt(date.length()-1) == 'Z') {
date.deleteCharAt(date.length()-1);
date.append("GMT-00:00");
} else {
date.insert(date.length()-6, "GMT");
}
}
return dateformat.parse(date.toString()); return dateformat.parse(date.toString());
} }

@ -4,71 +4,99 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.text.ParseException; import java.text.ParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import net.yacy.kelondro.logging.Log; import net.yacy.kelondro.logging.Log;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException; import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
public class YMarksXBELImporter extends DefaultHandler implements Runnable { public class YMarksXBELImporter extends DefaultHandler implements Runnable {
public static enum XBEL { public static enum XBEL {
NOTHING, NOTHING (""),
XBEL, XBEL ("<xbel"),
TITLE, TITLE ("<title"),
DESC, DESC ("<desc"),
BOOKMARK, BOOKMARK ("<bookmark"),
FOLDER, FOLDER ("<folder"),
SEPARATOR, SEPARATOR ("<separator"),
ALIAS, ALIAS ("<alias"),
INFO, INFO ("<info"),
METADATA; METADATA ("<metadata");
private static StringBuilder buffer = new StringBuilder(25);;
private String tag;
private XBEL(String t) {
this.tag = t;
}
public String tag() { public String tag() {
return this.toString().toLowerCase(); return this.toString().toLowerCase();
} }
public String endTag(boolean empty) {
buffer.setLength(0);
buffer.append(tag);
if(empty) {
buffer.append('/');
} else {
buffer.insert(1, '/');
}
buffer.append('>');
return buffer.toString();
}
public String startTag(boolean att) {
buffer.setLength(0);
buffer.append(tag);
if(!att)
buffer.append('>');
return buffer.toString();
}
} }
private HashMap<String,String> ref;
private HashMap<String,String> bmk; private HashMap<String,String> bmk;
private XBEL outer_state; // BOOKMARK, FOLDER, NOTHING private XBEL outer_state; // BOOKMARK, FOLDER, NOTHING
private XBEL inner_state; // DESC, TITLE, INFO, ALIAS, (METADATA), NOTHING private XBEL inner_state; // DESC, TITLE, INFO, ALIAS, (METADATA), NOTHING
private boolean parse_value; private boolean parse_value;
private final HashMap<String,HashMap<String,String>> bmkRef;
private final HashSet<HashMap<String,String>> aliasRef;
private final StringBuilder buffer; private final StringBuilder buffer;
private final StringBuilder folder; private final StringBuilder folder;
private final StringBuilder foldersString;
private final InputStream input; private final InputSource input;
private final ArrayBlockingQueue<HashMap<String,String>> bookmarks; private final ArrayBlockingQueue<HashMap<String,String>> bookmarks;
private final SAXParser saxParser; private final XMLReader xmlReader;
public YMarksXBELImporter (final InputStream input, int queueSize) throws SAXException { public YMarksXBELImporter (final InputStream input, int queueSize) throws SAXException {
this.bmk = null; this.bmk = null;
this.buffer = new StringBuilder(); this.buffer = new StringBuilder();
this.folder = new StringBuilder(YMarkTables.FOLDER_BUFFER_SIZE); this.foldersString = new StringBuilder(YMarkTables.FOLDER_BUFFER_SIZE);
this.folder = new StringBuilder(YMarkTables.FOLDER_BUFFER_SIZE);
this.folder.append(YMarkTables.FOLDERS_IMPORTED); this.folder.append(YMarkTables.FOLDERS_IMPORTED);
this.bookmarks = new ArrayBlockingQueue<HashMap<String,String>>(queueSize); this.bmkRef = new HashMap<String,HashMap<String,String>>();
this.input = input; this.aliasRef = new HashSet<HashMap<String,String>>();
final SAXParserFactory factory = SAXParserFactory.newInstance(); this.bookmarks = new ArrayBlockingQueue<HashMap<String,String>>(queueSize);
try { this.input = new InputSource(input);
this.saxParser = factory.newSAXParser(); this.xmlReader = XMLReaderFactory.createXMLReader();
} catch (ParserConfigurationException e) { this.xmlReader.setContentHandler(this);
Log.logException(e); this.xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
throw new SAXException (e.getMessage()); this.xmlReader.setFeature("http://xml.org/sax/features/namespaces", false);
} this.xmlReader.setFeature("http://xml.org/sax/features/validation", false);
} }
public void run() { public void run() {
try { try {
this.saxParser.parse(this.input, this); this.xmlReader.parse(this.input);
} catch (SAXParseException e) { } catch (SAXParseException e) {
Log.logException(e); Log.logException(e);
} catch (SAXException e) { } catch (SAXException e) {
Log.logException(e); Log.logException(e);
} catch (IOException e) { } catch (IOException e) {
@ -79,38 +107,41 @@ public class YMarksXBELImporter extends DefaultHandler implements Runnable {
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
Log.logException(e1); Log.logException(e1);
} }
try {
this.input.close();
} catch (IOException e) {
Log.logException(e);
}
} }
} }
public void endDocument() throws SAXException {
// no need to keep the bookmark references any longer
// this.bmkRef.clear();
}
public void startElement(final String uri, final String name, String tag, final Attributes atts) throws SAXException { public void startElement(final String uri, final String name, String tag, final Attributes atts) throws SAXException {
String date; String date;
if (tag == null) return; if (tag == null) return;
tag = tag.toLowerCase(); tag = tag.toLowerCase();
if (XBEL.BOOKMARK.tag().equals(tag)) { if (XBEL.BOOKMARK.tag().equals(tag)) {
this.bmk = new HashMap<String,String>(); this.bmk = new HashMap<String,String>();
this.bmk.put(YMarkTables.BOOKMARK.URL.key(), atts.getValue(uri, YMarkTables.BOOKMARK.URL.xbel_attrb())); this.bmk.put(YMarkTables.BOOKMARK.URL.key(), atts.getValue(uri, YMarkTables.BOOKMARK.URL.xbel_attrb()));
try { try {
date = String.valueOf(YMarkTables.parseISO8601(atts.getValue(uri, YMarkTables.BOOKMARK.DATE_ADDED.xbel_attrb()))); date = String.valueOf(YMarkTables.parseISO8601(atts.getValue(uri, YMarkTables.BOOKMARK.DATE_ADDED.xbel_attrb())).getTime());
} catch (ParseException e) { } catch (ParseException e) {
date = String.valueOf(System.currentTimeMillis()); date = String.valueOf(System.currentTimeMillis());
} }
this.bmk.put(YMarkTables.BOOKMARK.DATE_ADDED.key(), date); this.bmk.put(YMarkTables.BOOKMARK.DATE_ADDED.key(), date);
try { try {
date = String.valueOf(YMarkTables.parseISO8601(atts.getValue(uri, YMarkTables.BOOKMARK.DATE_VISITED.xbel_attrb()))); date = String.valueOf(YMarkTables.parseISO8601(atts.getValue(uri, YMarkTables.BOOKMARK.DATE_VISITED.xbel_attrb())).getTime());
this.bmk.put(YMarkTables.BOOKMARK.DATE_VISITED.key(), date);
} catch (ParseException e) { } catch (ParseException e) {
} date = YMarkTables.BOOKMARK.DATE_VISITED.deflt();
}
this.bmk.put(YMarkTables.BOOKMARK.DATE_VISITED.key(), date);
try { try {
date = String.valueOf(YMarkTables.parseISO8601(atts.getValue(uri, YMarkTables.BOOKMARK.DATE_MODIFIED.xbel_attrb()))); date = String.valueOf(YMarkTables.parseISO8601(atts.getValue(uri, YMarkTables.BOOKMARK.DATE_MODIFIED.xbel_attrb())).getTime());
} catch (ParseException e) { } catch (ParseException e) {
date = String.valueOf(System.currentTimeMillis()); date = String.valueOf(System.currentTimeMillis());
} }
this.bmk.put(YMarkTables.BOOKMARK.DATE_MODIFIED.key(), date); this.bmk.put(YMarkTables.BOOKMARK.DATE_MODIFIED.key(), date);
UpdateBmkRef(atts.getValue(uri, "id"), true);
outer_state = XBEL.BOOKMARK; outer_state = XBEL.BOOKMARK;
inner_state = XBEL.NOTHING; inner_state = XBEL.NOTHING;
this.parse_value = false; this.parse_value = false;
@ -128,24 +159,19 @@ public class YMarksXBELImporter extends DefaultHandler implements Runnable {
this.parse_value = false; this.parse_value = false;
} else if (XBEL.METADATA.tag().equals(tag)) { } else if (XBEL.METADATA.tag().equals(tag)) {
/* /*
this.meta_owner = atts.getValue(uri, "owner"); atts.getValue(uri, "owner");
this.inner_state = XBEL.METADATA;
this.parse_value = true;
*/ */
} else if (XBEL.ALIAS.tag().equals(tag)) { } else if (XBEL.ALIAS.tag().equals(tag)) {
// TODO: handle xbel aliases Log.logInfo(YMarkTables.BOOKMARKS_LOG, "ALIAS: "+this.ref.get(YMarkTables.BOOKMARK.URL.key()));
/* final String r = atts.getValue(uri, "ref");
this.alias_ref = atts.getValue(uri, "ref"); UpdateBmkRef(r, false);
this.inner_state = XBEL.ALIAS; this.aliasRef.add(this.bmkRef.get(r));
this.parse_value = false;
*/
} }
else { else {
this.outer_state = XBEL.NOTHING; this.outer_state = XBEL.NOTHING;
this.inner_state = XBEL.NOTHING; this.inner_state = XBEL.NOTHING;
this.parse_value = false; this.parse_value = false;
} }
} }
public void endElement(final String uri, final String name, String tag) { public void endElement(final String uri, final String name, String tag) {
@ -153,8 +179,8 @@ public class YMarksXBELImporter extends DefaultHandler implements Runnable {
tag = tag.toLowerCase(); tag = tag.toLowerCase();
if(XBEL.BOOKMARK.tag().equals(tag)) { if(XBEL.BOOKMARK.tag().equals(tag)) {
// write bookmark // write bookmark
if (!this.bmk.isEmpty()) { if (!this.bmk.isEmpty()) {
this.bmk.put(YMarkTables.BOOKMARK.FOLDERS.key(), this.folder.toString()); this.bmk.put(YMarkTables.BOOKMARK.FOLDERS.key(), this.folder.toString());
try { try {
this.bookmarks.put(this.bmk); this.bookmarks.put(this.bmk);
bmk = new HashMap<String,String>(); bmk = new HashMap<String,String>();
@ -191,7 +217,6 @@ public class YMarksXBELImporter extends DefaultHandler implements Runnable {
break; break;
case METADATA: case METADATA:
// TODO: handle xbel bookmark metadata // TODO: handle xbel bookmark metadata
// this.meta_data = this.buffer.toString();
break; break;
default: default:
break; break;
@ -207,7 +232,6 @@ public class YMarksXBELImporter extends DefaultHandler implements Runnable {
break; break;
case METADATA: case METADATA:
// TODO: handle xbel folder metadata // TODO: handle xbel folder metadata
// this.meta_data = this.buffer.toString();
break; break;
default: default:
break; break;
@ -229,4 +253,25 @@ public class YMarksXBELImporter extends DefaultHandler implements Runnable {
return null; return null;
} }
} }
public HashSet<HashMap<String,String>> getAliases() {
return this.aliasRef;
}
private void UpdateBmkRef(final String id, final boolean url) {
this.foldersString.setLength(0);
if(this.bmkRef.containsKey(id)) {
this.foldersString.append(this.bmkRef.get(id).get(YMarkTables.BOOKMARK.FOLDERS.key()));
this.foldersString.append(',');
this.ref = this.bmkRef.get(id);
} else {
this.ref = new HashMap<String,String>();
}
this.foldersString.append(this.folder);
if(url)
this.ref.put(YMarkTables.BOOKMARK.URL.key(), this.bmk.get(YMarkTables.BOOKMARK.URL.key()));
this.ref.put(YMarkTables.BOOKMARK.FOLDERS.key(), this.foldersString.toString());
this.bmkRef.put(id, ref);
}
} }

Loading…
Cancel
Save