a update to ymarks (please test if you wish):

- import HTML (e.g. FF export) via /api/ymarks/import.html
- view your import via /api/ymarks/test.html
- get a xml list via /api/ymarks/get_ymark_list.xml?tags=&folders=
- delete bookmark tables via standard interface /Tables_p.html
it is still very experimental!! 

git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@7299 6c8d7289-2bf4-0310-a012-ef5d649a1542
This commit is contained in:
apfelmaennchen 2010-11-03 22:52:03 +00:00
parent 93c535d111
commit 43586a2ace
11 changed files with 405 additions and 24 deletions

View File

@ -0,0 +1,91 @@
import java.io.IOException;
import java.util.Iterator;
import java.util.TreeSet;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.kelondro.blob.Tables;
import net.yacy.kelondro.index.RowSpaceExceededException;
import net.yacy.kelondro.logging.Log;
import de.anomic.data.YMarkTables;
import de.anomic.data.userDB;
import de.anomic.search.Switchboard;
import de.anomic.server.serverObjects;
import de.anomic.server.serverSwitch;
public class get_ymark_list {
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();
boolean tags = false;
final userDB.Entry user = sb.userDB.getUser(header);
final boolean isAdmin = (sb.verifyAuthentication(header, true));
final boolean isAuthUser = user!= null && user.hasRight(userDB.Entry.BOOKMARK_RIGHT);
final TreeSet<String> bookmarks = new TreeSet<String>();
if(isAdmin || isAuthUser) {
final String bmk_user = (isAuthUser ? user.getUserName() : YMarkTables.USER_ADMIN);
if(post.containsKey(YMarkTables.BOOKMARK.TAGS.key())) {
tags = true;
final String[] tagArray = YMarkTables.cleanTagsString(post.get(YMarkTables.BOOKMARK.TAGS.key())).split(YMarkTables.TAGS_SEPARATOR);
try {
bookmarks.addAll(sb.tables.bookmarks.tags.getBookmarks(bmk_user, tagArray));
} catch (IOException e) {
Log.logException(e);
} catch (RowSpaceExceededException e) {
Log.logException(e);
}
}
if(post.containsKey(YMarkTables.BOOKMARK.FOLDERS.key())) {
final String[] folderArray = YMarkTables.cleanFoldersString(post.get(YMarkTables.BOOKMARK.FOLDERS.key())).split(YMarkTables.TAGS_SEPARATOR);
try {
if(tags)
bookmarks.retainAll(sb.tables.bookmarks.folders.getBookmarks(bmk_user, folderArray));
else
bookmarks.addAll(sb.tables.bookmarks.folders.getBookmarks(bmk_user, folderArray));
} catch (IOException e) {
Log.logException(e);
} catch (RowSpaceExceededException e) {
Log.logException(e);
}
}
putBookmarks(bookmarks, YMarkTables.TABLES.BOOKMARKS.tablename(bmk_user));
} else {
prop.put(YMarkTables.USER_AUTHENTICATE,YMarkTables.USER_AUTHENTICATE_MSG);
}
// return rewrite properties
return prop;
}
private static void putBookmarks(final TreeSet<String> urlSet, final String bmk_table) {
final Iterator<String>urlIter = urlSet.iterator();
int count = 0;
while(urlIter.hasNext()) {
final byte[] urlHash = urlIter.next().getBytes();
Tables.Row bmk_row = null;
try {
bmk_row = sb.tables.select(bmk_table, urlHash);
if (bmk_row != null) {
prop.putXML("bookmarks_"+count+"_id", new String(urlHash));
for (YMarkTables.BOOKMARK bmk : YMarkTables.BOOKMARK.values()) {
prop.putXML("bookmarks_"+count+"_"+bmk.key(), new String(bmk_row.get(bmk.key(),bmk.deflt())));
}
count++;
}
} catch (IOException e) {
Log.logException(e);
} catch (RowSpaceExceededException e) {
Log.logException(e);
}
}
prop.put("bookmarks", count);
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<posts>
#{bookmarks}#
<post href="#[url]#" id="#[id]#" title="#[title]#" tag="#[tags]#" folders="#[folders]#" added="#[date_added]#"/>
#{/bookmarks}#
</posts>

View File

@ -0,0 +1,176 @@
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.kelondro.blob.Tables;
import net.yacy.kelondro.index.RowSpaceExceededException;
import net.yacy.kelondro.logging.Log;
import net.yacy.kelondro.util.DateFormatter;
import de.anomic.data.YMarkTables;
import de.anomic.data.userDB;
import de.anomic.search.Switchboard;
import de.anomic.server.serverObjects;
import de.anomic.server.serverSwitch;
public class get_ymark_tree {
public static final String ROOT = "root";
public static final String SOURCE = "source";
// for some reason enums don't work in servlet classes ?!?!
/*
private static final Map<String, String> TYPE = createMap();
private static Map<String, String> createMap() {
Map<String, String> result = new HashMap<String, String>();
result.put("tags", "tag");
result.put("url", "link");
result.put("public", "lock");
result.put("visits", "stat");
return Collections.unmodifiableMap(result);
}
*/
static serverObjects prop;
public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
final Switchboard 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.Entry.BOOKMARK_RIGHT);
if(isAdmin || isAuthUser) {
final String bmk_user = (isAuthUser ? user.getUserName() : YMarkTables.USER_ADMIN);
String root = YMarkTables.FOLDERS_ROOT;
String[] foldername = null;
boolean isFolder = true;
if (post != null){
if (post.containsKey(ROOT)) {
if (post.get(ROOT).equals(SOURCE) || post.get(ROOT).equals(YMarkTables.FOLDERS_ROOT)) {
root = "";
} else if (post.get(ROOT).startsWith(YMarkTables.FOLDERS_ROOT)) {
root = post.get(ROOT);
} else {
// root = YMarkTables.FOLDERS_ROOT + post.get(ROOT);
isFolder = false;
}
}
}
Iterator<String> it = null;
Tables.Row bmk_row = null;
int count = 0;
if(isFolder) {
// loop through folderList
try {
it = sb.tables.bookmarks.folders.getFolders(bmk_user, root);
} catch (IOException e) {
Log.logException(e);
}
int n = root.split(YMarkTables.FOLDERS_SEPARATOR).length;
if (n == 0) n = 1;
while (it.hasNext()) {
String folder = it.next();
foldername = folder.split(YMarkTables.FOLDERS_SEPARATOR);
if (foldername.length == n+1) {
prop.put("folders_"+count+"_foldername", foldername[n]);
prop.put("folders_"+count+"_expanded", "false");
prop.put("folders_"+count+"_type", "folder");
prop.put("folders_"+count+"_hash", folder); //TODO: switch from pathString to folderHash
prop.put("folders_"+count+"_url", ""); //TODO: insert folder url
prop.put("folders_"+count+"_hasChildren", "true"); //TODO: determine if folder has children
prop.put("folders_"+count+"_comma", ",");
count++;
}
}
// loop through bookmarkList
try {
it = sb.tables.bookmarks.folders.getBookmarks(bmk_user, root).iterator();
while (it.hasNext()) {
final String urlHash = new String(it.next());
bmk_row = sb.tables.select(YMarkTables.TABLES.BOOKMARKS.tablename(bmk_user), urlHash.getBytes());
if(bmk_row != null) {
final String url = new String(bmk_row.get(YMarkTables.BOOKMARK.URL.key()));
final String title = new String(bmk_row.get(YMarkTables.BOOKMARK.TITLE.key(), YMarkTables.BOOKMARK.TITLE.deflt()));
// TODO: get rid of bmtype
if (post.containsKey("bmtype")) {
if (post.get("bmtype").equals("title")) {
prop.put("folders_"+count+"_foldername", title);
} else if (post.get("bmtype").equals("href")) {
prop.put("folders_"+count+"_foldername",
"<a href='"+url+" 'target='_blank'>"+title+"</a>");
}
} else {
prop.put("folders_"+count+"_foldername", url);
}
prop.put("folders_"+count+"_expanded", "false");
prop.put("folders_"+count+"_url", url);
prop.put("folders_"+count+"_type", "file");
prop.put("folders_"+count+"_hash", urlHash);
prop.put("folders_"+count+"_hasChildren", "true");
prop.put("folders_"+count+"_comma", ",");
count++;
}
}
count--;
prop.put("folders_"+count+"_comma", "");
count++;
prop.put("folders", count);
} catch (IOException e) {
Log.logException(e);
} catch (RowSpaceExceededException e) {
Log.logException(e);
}
} else {
try {
bmk_row = sb.tables.select(YMarkTables.TABLES.BOOKMARKS.tablename(bmk_user), post.get(ROOT).getBytes());
if(bmk_row != null) {
it = bmk_row.keySet().iterator();
while(it.hasNext()) {
final String key = it.next();
if(key.startsWith("date")) {
final String date = DateFormatter.formatISO8601(new Date(Long.parseLong(new String(bmk_row.get(key)))));
prop.put("folders_"+count+"_foldername","<small><b>"+key+":</b> " + date + "</small>");
putProp(count, "date");
count++;
} else {
final String value = new String(bmk_row.get(key));
prop.put("folders_"+count+"_foldername","<small><b>"+key+":</b> " + value + "</small>");
if(YMarkTables.BOOKMARK.contains(key))
putProp(count, YMarkTables.BOOKMARK.get(key).type());
else
putProp(count, "meta");
count++;
}
}
count--;
prop.put("folders_"+count+"_comma", "");
count++;
prop.put("folders", count);
}
} catch (IOException e) {
Log.logException(e);
} catch (RowSpaceExceededException e) {
Log.logException(e);
}
}
}
// return rewrite properties
return prop;
}
public static void putProp(final int count, final String type) {
prop.put("folders_"+count+"_expanded", "false");
prop.put("folders_"+count+"_url", "");
prop.put("folders_"+count+"_type", type);
prop.put("folders_"+count+"_hash", "");
prop.put("folders_"+count+"_hasChildren", "false");
prop.put("folders_"+count+"_comma", ",");
}
}

View File

@ -0,0 +1,9 @@
[
#{folders}#{
"text": "#[foldername]#",
"expanded": #[expanded]#,
"classes": "#[type]#",
"id": "#[hash]#",
"hasChildren": #[hasChildren]#
}#[comma]##{/folders}#
]

View File

@ -0,0 +1,11 @@
<?xml version='1.0' encoding="UTF-8" standalone='yes'?>
<folders>
#{folders}#<folder
id="#[hash]#"
type="#[type]#"
name="#[foldername]#"
url="#[url]#"
hasChildren="#[hasChildren]#"
/>
#{/folders}#
</folders>

View File

@ -0,0 +1,38 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link media="screen" type="text/css" href="/yacy/ui/css/jquery.treeview.css" rel="stylesheet" />
<title>YaCy Bookmarks</title>
<script src="/yacy/ui/js/jquery-1.3.1.min.js" type="text/javascript"></script>
<script src="/yacy/ui/js/jquery.treeview.min.js" type="text/javascript"></script>
<script src="/yacy/ui/js/jquery.treeview.async.js" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
$("#yfolder").treeview({
url: "/api/ymarks/get_ymark_tree.json?bmtype=href",
unique: false,
toggle: function() {
}
});
});
$("button").click(function () {
alert("test");
});
//]]>
</script>
</head>
<body>
<h3>YaCy Bookmarks</h3>
<div>
<ul id="yfolder" class="filetree"></ul>
</div>
</body>
</html>

View File

@ -65,4 +65,17 @@
.filetree span.folder, .filetree span.file { padding: 1px 0px 0px 18px; display: block; }
.filetree span.folder { background: url(../img/treeview/folder.gif) 0 0 no-repeat; }
.filetree li.expandable span.folder { background: url(../img/treeview/folder-closed.gif) 0 0 no-repeat; }
.filetree span.file { background: url(../img/treeview/file.gif) 0 0 no-repeat; }
.filetree span.file { background: url(../img-2/article_text.png) 0 0 no-repeat; }
.filetree span.meta,
.filetree span.date,
.filetree span.lock,
.filetree span.stat,
.filetree span.link,
.filetree span.tag { padding: 2px 0px 0px 20px; display: block; }
.filetree span.meta { background: url(../img-2/code.png) 0 0 no-repeat; }
.filetree span.date { background: url(../img-2/calendar.png) 0 0 no-repeat; }
.filetree span.lock { background: url(../img-2/lock.png) 0 0 no-repeat; }
.filetree span.stat { background: url(../img-2/bar_graph.png) 0 0 no-repeat; }
.filetree span.link { background: url(../img-2/link.png) 0 0 no-repeat; }
.filetree span.tag { background: url(../img/tags/tag_blue.png) 0 0 no-repeat; }

View File

@ -40,7 +40,11 @@ public class YMarkIndex {
ADD,
REMOVE
}
public final static String PATTERN_PREFIX = "^";
public final static String PATTERN_POSTFIX = YMarkTables.FOLDERS_SEPARATOR + ".*$";
public final static String PATTERN_REPLACE = "("+YMarkTables.FOLDERS_SEPARATOR+".[^"+YMarkTables.FOLDERS_SEPARATOR+"]*$)";
private final WorkTables worktables;
private final String table_basename;
private final ConcurrentARC<String, byte[]> cache;
@ -51,24 +55,30 @@ public class YMarkIndex {
this.cache = new ConcurrentARC<String, byte[]>(50,1);
}
public String getKeyname(final String user, final byte[] key) throws IOException, RowSpaceExceededException {
final String index_table = user + this.table_basename;
Tables.Row row = this.worktables.select(index_table, key);
return new String(row.get(INDEX.NAME.key(), INDEX.NAME.deflt()));
}
public Iterator<String> getFolders(final String user, final String root) throws IOException {
final String index_table = user + this.table_basename;
final TreeSet<String> folders = new TreeSet<String>();
final Pattern r = Pattern.compile("^"+root);
final Pattern r = Pattern.compile(PATTERN_PREFIX + root + PATTERN_POSTFIX);
final Iterator<Row> it = this.worktables.iterator(index_table, INDEX.NAME.key(), r);
String path = "";
Row folder;
while (it.hasNext()) {
folder = it.next();
folder = it.next();
path = new String(folder.get(INDEX.NAME.key(), INDEX.NAME.deflt()));
while(path.length() > 0 && !path.equals(root)){
folders.add(path);
path = path.replaceAll("(/.[^/]*$)", "");
path = path.replaceAll(PATTERN_REPLACE, "");
}
}
if (!root.equals(YMarkTables.FOLDERS_ROOT)) { folders.add(root); }
if (!root.equals(YMarkTables.FOLDERS_ROOT)) { folders.add(root); }
return folders.iterator();
}

View File

@ -2,9 +2,12 @@ package de.anomic.data;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import net.yacy.kelondro.blob.Tables;
import net.yacy.kelondro.blob.Tables.Data;
import net.yacy.kelondro.data.meta.DigestURI;
@ -49,28 +52,42 @@ public class YMarkTables {
}
public static enum BOOKMARK {
URL ("url", "", "href", "href"),
TITLE ("title", "", "", ""),
DESC ("desc", "", "", ""),
DATE_ADDED ("date_added", "", "add_date", "added"),
DATE_MODIFIED ("date_modified", "", "last_modified", "modified"),
DATE_VISITED ("date_visited", "", "last_visited", "visited"),
PUBLIC ("public", "flase", "", ""),
TAGS ("tags", "unsorted", "shortcuturl", ""),
VISITS ("visits", "0", "", ""),
FOLDERS ("folders", "/unsorted", "", "");
URL ("url", "", "href", "href", "link"),
TITLE ("title", "", "", "", "meta"),
DESC ("desc", "", "", "", "comment"),
DATE_ADDED ("date_added", "", "add_date", "added", "date"),
DATE_MODIFIED ("date_modified", "", "last_modified", "modified", "date"),
DATE_VISITED ("date_visited", "", "last_visited", "visited", "date"),
PUBLIC ("public", "flase", "", "", "lock"),
TAGS ("tags", "unsorted", "shortcuturl", "", "tag"),
VISITS ("visits", "0", "", "", "stat"),
FOLDERS ("folders", "/unsorted", "", "", "folder");
private String key;
private String dflt;
private String html_attrb;
private String xbel_attrb;
private String type;
private static final Map<String,BOOKMARK> lookup = new HashMap<String,BOOKMARK>();
static {
for(BOOKMARK b : EnumSet.allOf(BOOKMARK.class))
lookup.put(b.key(), b);
}
private BOOKMARK(String k, String s, String a, String x) {
private BOOKMARK(String k, String s, String a, String x, String t) {
this.key = k;
this.dflt = s;
this.html_attrb = a;
this.xbel_attrb = x;
}
this.type = t;
}
public static BOOKMARK get(String key) {
return lookup.get(key);
}
public static boolean contains(String key) {
return lookup.containsKey(key);
}
public String key() {
return this.key;
}
@ -83,20 +100,30 @@ public class YMarkTables {
public String xbel_attrb() {
return this.xbel_attrb;
}
public String type() {
return this.type;
}
}
public final static HashMap<String,String> POISON = new HashMap<String,String>();
public final static String TAGS_SEPARATOR = ",";
public final static String FOLDERS_SEPARATOR = "/";
public final static String FOLDERS_ROOT = "/";
public final static String FOLDERS_UNSORTED = "/unsorted";
public final static String FOLDERS_IMPORTED = "/imported";
public final static String FOLDERS_IMPORTED = "/imported";
public final static String BOOKMARKS_LOG = "BOOKMARKS";
public final static String BOOKMARKS_ID = "id";
public final static String USER_ADMIN = "admin";
public final static String USER_ADMIN = "admin";
public final static String USER_AUTHENTICATE = "AUTHENTICATE";
public final static String USER_AUTHENTICATE_MSG = "Authentication required!";
private WorkTables worktables;
public YMarkIndex tags;
public YMarkIndex folders;
@ -177,7 +204,7 @@ public class YMarkTables {
}
return fs.toString();
}
public void clearIndex(String tablename) {
if (tablename.endsWith(TABLES.TAGS.basename()))
this.tags.clearCache();

View File

@ -134,7 +134,7 @@ public class YMarksHTMLImporter extends HTMLEditorKit.ParserCallback implements
state = STATE.FOLDER_DESC;
} else if (t == HTML.Tag.DL) {
if(!folder.equals(YMarkTables.FOLDERS_IMPORTED)) {
folder = folder.replaceAll("(/.[^/]*$)", "");
folder = folder.replaceAll(YMarkIndex.PATTERN_REPLACE, "");
}
} else {
state = STATE.NOTHING;

View File

@ -159,7 +159,7 @@ public class YMarksXBELImporter extends DefaultHandler implements Runnable {
this.state = STATE.NOTHING;
// go up one folder
if(!folder.equals(YMarkTables.FOLDERS_IMPORTED)) {
folder = folder.replaceAll("(/.[^/]*$)", "");
folder = folder.replaceAll(YMarkIndex.PATTERN_REPLACE, "");
this.state = STATE.FOLDER;
}
} else if (XBEL.INFO.tag().equals(tag)) {