2011-04-08 23:15:10 +02:00
// YMarkTables.java
// (C) 2011 by Stefan Förster, sof@gmx.de, Norderstedt, Germany
// first published 2010 on http://yacy.net
//
// This is a part of YaCy, a peer-to-peer based web search engine
//
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
//
// LICENSE
2011-06-22 01:10:50 +02:00
//
2011-04-08 23:15:10 +02:00
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2012-09-21 15:48:16 +02:00
package net.yacy.data.ymark ;
2011-04-08 23:15:10 +02:00
import java.io.IOException ;
2012-08-29 09:52:14 +02:00
import java.net.MalformedURLException ;
2011-11-14 23:00:44 +01:00
import java.util.ArrayList ;
import java.util.Collections ;
2011-11-23 00:50:49 +01:00
import java.util.EnumMap ;
2011-04-08 23:15:10 +02:00
import java.util.HashSet ;
import java.util.Iterator ;
2011-11-14 23:00:44 +01:00
import java.util.List ;
2012-09-09 09:53:58 +02:00
import java.util.Map ;
2011-05-01 23:42:48 +02:00
import java.util.TreeMap ;
2011-04-08 23:15:10 +02:00
import java.util.TreeSet ;
2012-09-09 09:53:58 +02:00
import java.util.concurrent.ConcurrentHashMap ;
import javax.swing.event.ChangeEvent ;
import javax.swing.event.ChangeListener ;
2011-04-08 23:15:10 +02:00
2013-09-15 00:30:23 +02:00
import net.yacy.cora.document.encoding.ASCII ;
import net.yacy.cora.document.id.DigestURL ;
2013-08-22 14:23:47 +02:00
import net.yacy.cora.protocol.ClientIdentification ;
2013-07-09 14:28:25 +02:00
import net.yacy.cora.util.ConcurrentLog ;
2012-07-27 12:13:53 +02:00
import net.yacy.cora.util.SpaceExceededException ;
2012-09-21 15:48:16 +02:00
import net.yacy.data.WorkTables ;
2011-11-23 00:50:49 +01:00
import net.yacy.document.Document ;
import net.yacy.document.Parser.Failure ;
2012-09-26 09:56:16 +02:00
import net.yacy.kelondro.blob.TableColumnIndexException ;
2011-04-08 23:15:10 +02:00
import net.yacy.kelondro.blob.Tables ;
2011-04-21 00:33:01 +02:00
import net.yacy.kelondro.blob.Tables.Row ;
2012-09-09 09:53:58 +02:00
import net.yacy.kelondro.blob.TablesColumnIndex ;
2011-11-23 00:50:49 +01:00
import net.yacy.repository.LoaderDispatcher ;
2011-04-08 23:15:10 +02:00
public class YMarkTables {
2011-06-22 01:10:50 +02:00
2011-04-16 11:09:33 +02:00
public static enum TABLES {
2011-04-08 23:15:10 +02:00
BOOKMARKS ( " _bookmarks " ) ,
TAGS ( " _tags " ) ,
FOLDERS ( " _folders " ) ;
2011-06-22 01:10:50 +02:00
2011-04-08 23:15:10 +02:00
private String basename ;
2011-06-22 01:10:50 +02:00
private TABLES ( final String b ) {
2011-04-08 23:15:10 +02:00
this . basename = b ;
}
public String basename ( ) {
return this . basename ;
}
2011-06-22 01:10:50 +02:00
public String tablename ( final String bmk_user ) {
2011-04-08 23:15:10 +02:00
return bmk_user + this . basename ;
}
}
2011-06-22 01:10:50 +02:00
2011-04-08 23:15:10 +02:00
public static enum PROTOCOLS {
HTTP ( " http:// " ) ,
HTTPS ( " https:// " ) ;
2011-06-22 01:10:50 +02:00
2011-04-08 23:15:10 +02:00
private String protocol ;
2011-06-22 01:10:50 +02:00
private PROTOCOLS ( final String s ) {
2011-04-08 23:15:10 +02:00
this . protocol = s ;
}
public String protocol ( ) {
return this . protocol ;
}
2011-06-22 01:10:50 +02:00
public String protocol ( final String s ) {
2011-04-08 23:15:10 +02:00
return this . protocol + s ;
}
}
2011-06-22 01:10:50 +02:00
public final static String FOLDERS_ROOT = " / " ;
2011-04-08 23:15:10 +02:00
public final static String BOOKMARKS_LOG = " BOOKMARKS " ;
public final static String USER_ADMIN = " admin " ;
2011-11-25 18:33:03 +01:00
public final static String USER_AUTHENTICATE_MSG = " Bookmark user authentication required! " ;
2011-06-22 01:10:50 +02:00
2011-05-01 23:42:48 +02:00
public final static int BUFFER_LENGTH = 256 ;
2011-06-22 01:10:50 +02:00
2011-04-16 11:09:33 +02:00
private final WorkTables worktables ;
2012-09-09 09:53:58 +02:00
private final Map < String , ChangeListener > progressListeners ;
2012-08-31 14:07:33 +02:00
2012-08-29 09:04:28 +02:00
public boolean dirty = false ;
2011-06-22 01:10:50 +02:00
2011-04-08 23:15:10 +02:00
public YMarkTables ( final Tables wt ) {
this . worktables = ( WorkTables ) wt ;
2012-09-09 09:53:58 +02:00
this . progressListeners = new ConcurrentHashMap < String , ChangeListener > ( ) ;
this . buildIndex ( ) ;
}
2012-09-10 07:05:20 +02:00
2012-09-09 09:53:58 +02:00
public ChangeListener getProgressListener ( String thread ) {
final ChangeListener l = new ProgressListener ( ) ;
this . progressListeners . put ( thread , l ) ;
return l ;
}
2012-09-10 07:05:20 +02:00
2012-09-09 09:53:58 +02:00
public void removeProgressListener ( String thread ) {
this . progressListeners . remove ( thread ) ;
}
2012-09-10 07:05:20 +02:00
2012-09-09 09:53:58 +02:00
public class ProgressListener implements ChangeListener {
// the progress in %
private int progress = 0 ;
2012-09-10 07:05:20 +02:00
@Override
public void stateChanged ( ChangeEvent e ) {
2012-09-09 09:53:58 +02:00
final MonitoredReader mreader = ( MonitoredReader ) e . getSource ( ) ;
this . progress = ( int ) ( ( mreader . getProgress ( ) / mreader . maxProgress ( ) ) * 100 ) ;
}
public int progress ( ) {
return this . progress ;
}
}
2012-09-10 07:05:20 +02:00
public void buildIndex ( ) {
2012-09-09 09:53:58 +02:00
final Iterator < String > iter = this . worktables . iterator ( ) ;
while ( iter . hasNext ( ) ) {
final String bmk_table = iter . next ( ) ;
if ( bmk_table . endsWith ( TABLES . BOOKMARKS . basename ( ) ) ) {
2012-09-10 07:05:20 +02:00
try {
2012-09-09 09:53:58 +02:00
final long time = System . currentTimeMillis ( ) ;
2012-09-10 07:05:20 +02:00
final TablesColumnIndex index = this . worktables . getIndex ( bmk_table ) ;
2012-09-09 09:53:58 +02:00
if ( index . getType ( ) = = TablesColumnIndex . INDEXTYPE . RAM | | index . size ( ) = = 0 ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . info ( YMarkTables . BOOKMARKS_LOG , " buildIndex() " + YMarkEntry . BOOKMARK . indexColumns ( ) . keySet ( ) . toString ( ) ) ;
2012-09-09 09:53:58 +02:00
index . buildIndex ( YMarkEntry . BOOKMARK . indexColumns ( ) , this . worktables . iterator ( bmk_table ) ) ;
2013-07-09 14:28:25 +02:00
ConcurrentLog . info ( YMarkTables . BOOKMARKS_LOG , " build " + index . getType ( ) . name ( ) + " index for columns " + YMarkEntry . BOOKMARK . indexColumns ( ) . keySet ( ) . toString ( )
2012-09-09 09:53:58 +02:00
+ " of table " + bmk_table + " containing " + this . worktables . size ( bmk_table ) + " bookmarks "
2012-09-10 07:05:20 +02:00
+ " ( " + ( System . currentTimeMillis ( ) - time ) + " ms) " ) ;
}
2013-07-17 18:31:30 +02:00
} catch ( final IOException e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . logException ( e ) ;
2013-07-17 18:31:30 +02:00
} catch ( final TableColumnIndexException e ) {
2012-09-26 09:56:16 +02:00
// currently nothing to do...
2012-09-09 09:53:58 +02:00
}
}
2012-09-10 07:05:20 +02:00
}
2011-04-08 23:15:10 +02:00
}
2011-06-22 01:10:50 +02:00
2012-07-27 12:13:53 +02:00
public void deleteBookmark ( final String bmk_user , final byte [ ] urlHash ) throws IOException , SpaceExceededException {
2011-04-08 23:15:10 +02:00
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
Tables . Row bmk_row = null ;
bmk_row = this . worktables . select ( bmk_table , urlHash ) ;
if ( bmk_row ! = null ) {
this . worktables . delete ( bmk_table , urlHash ) ;
}
2012-09-09 09:53:58 +02:00
if ( this . worktables . hasIndex ( bmk_table , YMarkEntry . BOOKMARK . FOLDERS . key ( ) ) ) {
2012-09-26 09:56:16 +02:00
try {
2012-09-09 09:53:58 +02:00
this . worktables . getIndex ( bmk_table ) . delete ( urlHash ) ;
2013-07-17 18:31:30 +02:00
} catch ( final TableColumnIndexException e ) {
2012-09-26 09:56:16 +02:00
// currently nothing to do...
2012-09-09 09:53:58 +02:00
}
}
2011-04-08 23:15:10 +02:00
}
2011-06-22 01:10:50 +02:00
2012-07-27 12:13:53 +02:00
public void deleteBookmark ( final String bmk_user , final String url ) throws IOException , SpaceExceededException {
2012-09-09 09:53:58 +02:00
final byte [ ] urlHash = YMarkUtil . getBookmarkId ( url ) ;
this . deleteBookmark ( bmk_user , urlHash ) ;
2011-04-08 23:15:10 +02:00
}
2011-06-22 01:10:50 +02:00
2011-05-02 16:05:51 +02:00
public TreeMap < String , YMarkTag > getTags ( final Iterator < Row > rowIterator ) {
2011-05-01 23:42:48 +02:00
final TreeMap < String , YMarkTag > tags = new TreeMap < String , YMarkTag > ( ) ;
Tables . Row bmk_row = null ;
Iterator < String > 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 ;
}
2011-06-22 01:10:50 +02:00
2011-05-01 23:42:48 +02:00
public TreeMap < String , YMarkTag > getTags ( final String bmk_user ) throws IOException {
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
2012-09-09 09:53:58 +02:00
final TreeMap < String , YMarkTag > tags = new TreeMap < String , YMarkTag > ( ) ;
if ( this . worktables . hasIndex ( bmk_table , YMarkEntry . BOOKMARK . TAGS . key ( ) ) ) {
try {
final TablesColumnIndex index = this . worktables . getIndex ( bmk_table ) ;
final Iterator < String > iter = index . keySet ( YMarkEntry . BOOKMARK . TAGS . key ( ) ) . iterator ( ) ;
while ( iter . hasNext ( ) ) {
final String tag = iter . next ( ) ;
tags . put ( tag , new YMarkTag ( tag , index . get ( YMarkEntry . BOOKMARK . TAGS . key ( ) , tag ) . size ( ) ) ) ;
}
return tags ;
2013-07-17 18:31:30 +02:00
} catch ( final Exception e ) {
2012-09-09 09:53:58 +02:00
// nothing to do
}
}
return getTags ( this . worktables . iterator ( bmk_table ) ) ;
2011-05-01 23:42:48 +02:00
}
2011-06-22 01:10:50 +02:00
2012-09-09 09:53:58 +02:00
public TreeSet < String > getFolders ( final String bmk_user , String root ) throws IOException {
2011-04-08 23:15:10 +02:00
final TreeSet < String > folders = new TreeSet < String > ( ) ;
2012-09-09 09:53:58 +02:00
final StringBuilder path = new StringBuilder ( BUFFER_LENGTH ) ;
final String r = root + YMarkUtil . FOLDERS_SEPARATOR ;
2012-09-10 07:05:20 +02:00
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
2011-06-22 01:10:50 +02:00
2012-09-09 09:53:58 +02:00
// if exists, try the index first
2012-09-10 07:05:20 +02:00
if ( this . worktables . hasIndex ( bmk_table , YMarkEntry . BOOKMARK . FOLDERS . key ( ) ) ) {
2012-09-09 09:53:58 +02:00
TablesColumnIndex index ;
try {
index = this . worktables . getIndex ( bmk_table ) ;
final Iterator < String > fiter = index . keySet ( YMarkEntry . BOOKMARK . FOLDERS . key ( ) ) . iterator ( ) ;
while ( fiter . hasNext ( ) ) {
final String folder = fiter . next ( ) ;
if ( folder . startsWith ( r ) ) {
path . setLength ( 0 ) ;
path . append ( folder ) ;
while ( path . length ( ) > 0 & & ! path . toString ( ) . equals ( root ) ) {
final String p = path . toString ( ) ;
if ( folders . isEmpty ( ) | | ! p . equals ( folders . floor ( p ) ) ) {
folders . add ( p ) ;
2012-09-10 07:05:20 +02:00
}
2012-09-09 09:53:58 +02:00
path . setLength ( path . lastIndexOf ( YMarkUtil . FOLDERS_SEPARATOR ) ) ;
}
}
}
if ( ! root . equals ( YMarkTables . FOLDERS_ROOT ) ) { folders . add ( root ) ; }
2012-09-10 07:05:20 +02:00
return folders ;
2013-07-17 18:31:30 +02:00
} catch ( final Exception e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . logException ( e ) ;
2012-09-09 09:53:58 +02:00
}
}
2012-09-10 07:05:20 +02:00
2012-09-09 09:53:58 +02:00
// by default iterate all bookmarks and extract folder information
2012-09-10 07:05:20 +02:00
final Iterator < Tables . Row > bit = this . worktables . iterator ( bmk_table ) ;
Tables . Row bmk_row = null ;
2011-04-08 23:15:10 +02:00
while ( bit . hasNext ( ) ) {
bmk_row = bit . next ( ) ;
2011-06-22 01:10:50 +02:00
if ( bmk_row . containsKey ( YMarkEntry . BOOKMARK . FOLDERS . key ( ) ) ) {
2013-12-12 11:50:48 +01:00
final String [ ] folderArray = YMarkUtil . TAGS_SEPARATOR_PATTERN . split ( new String ( bmk_row . get ( YMarkEntry . BOOKMARK . FOLDERS . key ( ) ) , " UTF8 " ) ) ;
2011-04-08 23:15:10 +02:00
for ( final String folder : folderArray ) {
2012-09-09 09:53:58 +02:00
if ( folder . length ( ) > root . length ( ) & & folder . substring ( 0 , root . length ( ) + 1 ) . equals ( r ) ) {
2011-04-16 23:19:42 +02:00
if ( ! folders . contains ( folder ) ) {
2011-04-08 23:15:10 +02:00
path . setLength ( 0 ) ;
path . append ( folder ) ;
//TODO: get rid of .toString.equals()
while ( path . length ( ) > 0 & & ! path . toString ( ) . equals ( root ) ) {
2011-06-22 01:10:50 +02:00
folders . add ( path . toString ( ) ) ;
2011-04-16 23:19:42 +02:00
path . setLength ( path . lastIndexOf ( YMarkUtil . FOLDERS_SEPARATOR ) ) ;
2011-06-22 01:10:50 +02:00
}
2011-04-08 23:15:10 +02:00
}
2011-06-22 01:10:50 +02:00
}
2011-04-08 23:15:10 +02:00
}
}
}
2012-09-09 09:53:58 +02:00
if ( ! root . equals ( YMarkTables . FOLDERS_ROOT ) ) { folders . add ( root ) ; }
2012-09-10 07:05:20 +02:00
return folders ;
2011-04-08 23:15:10 +02:00
}
2011-06-22 01:10:50 +02:00
2012-09-09 09:53:58 +02:00
public int getSize ( final String bmk_user ) throws IOException {
2011-04-08 23:15:10 +02:00
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
2012-09-09 09:53:58 +02:00
return this . worktables . size ( bmk_table ) ;
2011-04-08 23:15:10 +02:00
}
2011-11-24 15:57:09 +01:00
2012-09-09 09:53:58 +02:00
public Iterator < Tables . Row > getBookmarksByFolder ( final String bmk_user , final String foldersString ) {
2012-09-10 07:05:20 +02:00
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
return this . worktables . getByIndex ( bmk_table , YMarkEntry . BOOKMARK . FOLDERS . key ( ) , YMarkEntry . BOOKMARK . FOLDERS . seperator ( ) , foldersString ) ;
2011-04-08 23:15:10 +02:00
}
2012-08-31 14:07:33 +02:00
2012-09-09 09:53:58 +02:00
public Iterator < Tables . Row > getBookmarksByTag ( final String bmk_user , final String tagsString ) {
2012-09-10 07:05:20 +02:00
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
return this . worktables . getByIndex ( bmk_table , YMarkEntry . BOOKMARK . TAGS . key ( ) , YMarkEntry . BOOKMARK . TAGS . seperator ( ) , tagsString ) ;
2012-08-29 09:04:28 +02:00
}
2011-11-24 15:57:09 +01:00
2011-11-14 23:00:44 +01:00
public List < Row > orderBookmarksBy ( final Iterator < Row > rowIterator , final String sortname , final String sortorder ) {
final List < Row > sortList = new ArrayList < Row > ( ) ;
2011-04-21 00:33:01 +02:00
Row row ;
while ( rowIterator . hasNext ( ) ) {
row = rowIterator . next ( ) ;
if ( row ! = null )
2011-11-14 23:00:44 +01:00
sortList . add ( row ) ;
2011-04-21 00:33:01 +02:00
}
2011-11-24 15:57:09 +01:00
Collections . sort ( sortList , new TablesRowComparator ( sortname , sortorder ) ) ;
2011-11-14 23:00:44 +01:00
return sortList ;
2011-04-21 00:33:01 +02:00
}
2011-06-22 01:10:50 +02:00
2012-08-31 14:07:33 +02:00
public void addTags ( final String bmk_user , final String url , final String tagString , final boolean merge ) throws IOException {
2011-05-01 23:42:48 +02:00
if ( ! tagString . isEmpty ( ) ) {
// do not set defaults as we only want to update tags
final YMarkEntry bmk = new YMarkEntry ( false ) ;
2011-06-22 01:10:50 +02:00
bmk . put ( YMarkEntry . BOOKMARK . URL . key ( ) , url ) ;
2011-05-01 23:42:48 +02:00
bmk . put ( YMarkEntry . BOOKMARK . TAGS . key ( ) , YMarkUtil . cleanTagsString ( tagString ) ) ;
2011-06-22 01:10:50 +02:00
addBookmark ( bmk_user , bmk , merge , true ) ;
}
2012-08-31 14:07:33 +02:00
this . dirty = true ;
2011-05-01 23:42:48 +02:00
}
2011-11-24 15:57:09 +01:00
2012-07-05 09:21:27 +02:00
public void replaceTags ( final Iterator < Row > rowIterator , final String bmk_user , final String tagString , final String replaceString ) throws IOException {
2012-09-09 09:53:58 +02:00
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
2012-07-05 09:21:27 +02:00
final HashSet < String > remove = YMarkUtil . keysStringToSet ( YMarkUtil . cleanTagsString ( tagString . toLowerCase ( ) ) ) ;
2011-11-25 01:32:18 +01:00
final StringBuilder t = new StringBuilder ( 200 ) ;
HashSet < String > tags ;
2011-11-19 21:59:21 +01:00
Row row ;
while ( rowIterator . hasNext ( ) ) {
row = rowIterator . next ( ) ;
if ( row ! = null ) {
2011-11-25 01:32:18 +01:00
tags = YMarkUtil . keysStringToSet ( row . get ( YMarkEntry . BOOKMARK . TAGS . key ( ) , YMarkEntry . BOOKMARK . TAGS . deflt ( ) ) . toLowerCase ( ) ) ;
tags . removeAll ( remove ) ;
t . append ( YMarkUtil . keySetToString ( tags ) ) ;
2011-11-24 15:57:09 +01:00
}
2011-11-25 01:32:18 +01:00
t . append ( YMarkUtil . TAGS_SEPARATOR ) ;
t . append ( replaceString ) ;
row . put ( YMarkEntry . BOOKMARK . TAGS . key ( ) , YMarkUtil . cleanTagsString ( t . toString ( ) ) ) ;
2012-09-09 09:53:58 +02:00
this . worktables . update ( bmk_table , row ) ;
if ( this . worktables . hasIndex ( bmk_table ) ) {
try {
this . worktables . getIndex ( bmk_table ) . update ( YMarkEntry . BOOKMARK . TAGS . key ( ) , YMarkEntry . BOOKMARK . TAGS . seperator ( ) , row ) ;
2013-07-17 18:31:30 +02:00
} catch ( final Exception e ) {
2012-09-09 09:53:58 +02:00
// nothing to do
}
}
2011-11-19 21:59:21 +01:00
}
2012-08-31 14:07:33 +02:00
this . dirty = true ;
2011-11-19 21:59:21 +01:00
}
2011-06-22 01:10:50 +02:00
2012-08-31 14:07:33 +02:00
public void addFolder ( final String bmk_user , final String url , final String folder ) throws IOException {
2011-05-03 23:21:06 +02:00
if ( ! folder . isEmpty ( ) ) {
// do not set defaults as we only want to add a folder
final YMarkEntry bmk = new YMarkEntry ( false ) ;
2011-06-22 01:10:50 +02:00
bmk . put ( YMarkEntry . BOOKMARK . URL . key ( ) , url ) ;
2011-05-03 23:21:06 +02:00
bmk . put ( YMarkEntry . BOOKMARK . FOLDERS . key ( ) , folder ) ;
2011-06-22 01:10:50 +02:00
addBookmark ( bmk_user , bmk , true , true ) ;
}
2011-05-03 23:21:06 +02:00
}
2011-06-22 01:10:50 +02:00
2012-08-31 14:07:33 +02:00
public void visited ( final String bmk_user , final String url ) throws IOException {
2011-05-03 23:21:06 +02:00
// do not set defaults
final YMarkEntry bmk = new YMarkEntry ( false ) ;
2011-06-22 01:10:50 +02:00
bmk . put ( YMarkEntry . BOOKMARK . URL . key ( ) , url ) ;
2011-05-03 23:21:06 +02:00
bmk . put ( YMarkEntry . BOOKMARK . DATE_VISITED . key ( ) , ( new YMarkDate ( ) ) . toString ( ) ) ;
2011-06-22 01:10:50 +02:00
addBookmark ( bmk_user , bmk , true , true ) ;
2011-05-03 23:21:06 +02:00
}
2011-11-24 15:57:09 +01:00
2013-08-22 14:23:47 +02:00
public void createBookmark ( final LoaderDispatcher loader , final String url , final ClientIdentification . Agent agent , final String bmk_user , final boolean autotag , final String tagsString , final String foldersString ) throws IOException , Failure {
2013-09-15 00:30:23 +02:00
createBookmark ( loader , new DigestURL ( url ) , agent , bmk_user , autotag , tagsString , foldersString ) ;
2011-11-23 00:50:49 +01:00
}
2011-11-24 15:57:09 +01:00
2013-09-15 00:30:23 +02:00
public void createBookmark ( final LoaderDispatcher loader , final DigestURL url , final ClientIdentification . Agent agent , final String bmk_user , final boolean autotag , final String tagsString , final String foldersString ) throws IOException , Failure {
2011-11-24 15:57:09 +01:00
final YMarkEntry bmk_entry = new YMarkEntry ( false ) ;
2011-11-23 00:50:49 +01:00
final YMarkMetadata meta = new YMarkMetadata ( url ) ;
2013-08-22 14:23:47 +02:00
final Document document = meta . loadDocument ( loader , agent ) ;
2011-11-24 15:57:09 +01:00
final EnumMap < YMarkMetadata . METADATA , String > metadata = meta . loadMetadata ( ) ;
2012-10-10 11:46:22 +02:00
final String urls = url . toNormalform ( true ) ;
2011-11-24 15:57:09 +01:00
bmk_entry . put ( YMarkEntry . BOOKMARK . URL . key ( ) , urls ) ;
if ( ! this . worktables . has ( YMarkTables . TABLES . BOOKMARKS . tablename ( bmk_user ) , YMarkUtil . getBookmarkId ( urls ) ) ) {
2011-11-23 00:50:49 +01:00
bmk_entry . put ( YMarkEntry . BOOKMARK . PUBLIC . key ( ) , " false " ) ;
bmk_entry . put ( YMarkEntry . BOOKMARK . TITLE . key ( ) , metadata . get ( YMarkMetadata . METADATA . TITLE ) ) ;
2011-11-24 15:57:09 +01:00
bmk_entry . put ( YMarkEntry . BOOKMARK . DESC . key ( ) , metadata . get ( YMarkMetadata . METADATA . DESCRIPTION ) ) ;
2011-11-23 00:50:49 +01:00
}
2011-11-25 18:33:03 +01:00
final String fs = YMarkUtil . cleanFoldersString ( foldersString ) ;
if ( fs . isEmpty ( ) )
bmk_entry . put ( YMarkEntry . BOOKMARK . FOLDERS . key ( ) , YMarkEntry . BOOKMARK . FOLDERS . deflt ( ) ) ;
else
bmk_entry . put ( YMarkEntry . BOOKMARK . FOLDERS . key ( ) , fs ) ;
2011-11-23 00:50:49 +01:00
final StringBuilder strb = new StringBuilder ( ) ;
2011-11-24 15:57:09 +01:00
if ( autotag ) {
2011-11-23 00:50:49 +01:00
final String autotags = YMarkAutoTagger . autoTag ( document , 3 , this . worktables . bookmarks . getTags ( bmk_user ) ) ;
strb . append ( autotags ) ;
}
if ( ! tagsString . isEmpty ( ) ) {
strb . append ( YMarkUtil . TAGS_SEPARATOR ) ;
strb . append ( tagsString ) ;
}
2011-11-24 15:57:09 +01:00
bmk_entry . put ( YMarkEntry . BOOKMARK . TAGS . key ( ) , YMarkUtil . cleanTagsString ( strb . toString ( ) ) ) ;
2011-11-23 00:50:49 +01:00
this . worktables . bookmarks . addBookmark ( bmk_user , bmk_entry , true , true ) ;
}
2011-11-24 15:57:09 +01:00
public boolean hasBookmark ( final String bmk_user , final String urlhash ) {
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
try {
return this . worktables . has ( bmk_table , ASCII . getBytes ( urlhash ) ) ;
} catch ( final IOException e ) {
return false ;
}
}
2012-08-31 14:07:33 +02:00
public void addBookmark ( final String bmk_user , final YMarkEntry bmk , final boolean mergeTags , final boolean mergeFolders ) throws IOException {
2011-04-08 23:15:10 +02:00
final String bmk_table = TABLES . BOOKMARKS . tablename ( bmk_user ) ;
final String date = String . valueOf ( System . currentTimeMillis ( ) ) ;
2012-08-29 09:52:14 +02:00
byte [ ] urlHash = null ;
try {
urlHash = YMarkUtil . getBookmarkId ( bmk . get ( YMarkEntry . BOOKMARK . URL . key ( ) ) ) ;
2013-07-17 18:31:30 +02:00
} catch ( final MalformedURLException e ) {
2013-07-09 14:28:25 +02:00
ConcurrentLog . info ( " BOOKMARKIMPORT " , " invalid url: " + bmk . get ( YMarkEntry . BOOKMARK . URL . key ( ) ) ) ;
2012-08-29 09:52:14 +02:00
}
2011-04-08 23:15:10 +02:00
Tables . Row bmk_row = null ;
if ( urlHash ! = null ) {
2012-08-29 09:52:14 +02:00
try {
bmk_row = this . worktables . select ( bmk_table , urlHash ) ;
2013-07-17 18:31:30 +02:00
} catch ( final Exception e ) {
2012-08-31 14:07:33 +02:00
2012-08-29 09:52:14 +02:00
}
2011-04-08 23:15:10 +02:00
if ( bmk_row = = null ) {
// create and insert new entry
2011-11-17 00:10:53 +01:00
if ( ! bmk . containsKey ( YMarkEntry . BOOKMARK . DATE_ADDED . key ( ) ) ) {
bmk . put ( YMarkEntry . BOOKMARK . DATE_ADDED . key ( ) , date ) ;
bmk . put ( YMarkEntry . BOOKMARK . DATE_MODIFIED . key ( ) , date ) ;
}
this . worktables . insert ( bmk_table , urlHash , bmk . getData ( ) ) ;
2012-09-09 09:53:58 +02:00
try {
if ( this . worktables . hasIndex ( bmk_table ) )
this . worktables . getIndex ( bmk_table ) . add ( YMarkEntry . BOOKMARK . indexColumns ( ) , bmk , urlHash ) ;
2013-07-17 18:31:30 +02:00
} catch ( final Exception e ) {
2012-09-09 09:53:58 +02:00
// nothing to do
}
2011-06-22 01:10:50 +02:00
} else {
2011-05-01 23:42:48 +02:00
// modify and update existing entry
2011-04-08 23:15:10 +02:00
HashSet < String > oldSet ;
HashSet < String > newSet ;
2011-06-22 01:10:50 +02:00
for ( final YMarkEntry . BOOKMARK b : YMarkEntry . BOOKMARK . values ( ) ) {
2011-04-08 23:15:10 +02:00
switch ( b ) {
case DATE_ADDED :
2011-04-18 23:42:14 +02:00
if ( ! bmk_row . containsKey ( b . key ( ) ) )
2011-06-22 01:10:50 +02:00
bmk_row . put ( b . key ( ) , date ) ;
2011-04-08 23:15:10 +02:00
break ;
case DATE_MODIFIED :
2011-06-22 01:10:50 +02:00
bmk_row . put ( b . key ( ) , date ) ;
2011-04-08 23:15:10 +02:00
break ;
case TAGS :
oldSet = YMarkUtil . keysStringToSet ( bmk_row . get ( b . key ( ) , b . deflt ( ) ) ) ;
if ( bmk . containsKey ( b . key ( ) ) ) {
newSet = YMarkUtil . keysStringToSet ( bmk . get ( b . key ( ) ) ) ;
2011-05-01 23:42:48 +02:00
if ( mergeTags ) {
2011-04-08 23:15:10 +02:00
newSet . addAll ( oldSet ) ;
2011-05-01 23:42:48 +02:00
if ( newSet . size ( ) > 1 & & newSet . contains ( YMarkEntry . BOOKMARK . TAGS . deflt ( ) ) )
newSet . remove ( YMarkEntry . BOOKMARK . TAGS . deflt ( ) ) ;
2011-04-08 23:15:10 +02:00
bmk_row . put ( b . key ( ) , YMarkUtil . keySetToString ( newSet ) ) ;
} else {
2011-04-18 23:42:14 +02:00
bmk_row . put ( b . key ( ) , bmk . get ( b . key ( ) ) ) ;
2011-04-08 23:15:10 +02:00
}
} else {
2011-04-18 23:42:14 +02:00
bmk_row . put ( b . key ( ) , bmk_row . get ( b . key ( ) , b . deflt ( ) ) ) ;
2011-06-22 01:10:50 +02:00
}
2011-04-08 23:15:10 +02:00
break ;
case FOLDERS :
oldSet = YMarkUtil . keysStringToSet ( bmk_row . get ( b . key ( ) , b . deflt ( ) ) ) ;
if ( bmk . containsKey ( b . key ( ) ) ) {
newSet = YMarkUtil . keysStringToSet ( bmk . get ( b . key ( ) ) ) ;
2011-05-01 23:42:48 +02:00
if ( mergeFolders ) {
2011-04-08 23:15:10 +02:00
newSet . addAll ( oldSet ) ;
2011-05-01 23:42:48 +02:00
if ( newSet . size ( ) > 1 & & newSet . contains ( YMarkEntry . BOOKMARK . FOLDERS . deflt ( ) ) )
newSet . remove ( YMarkEntry . BOOKMARK . FOLDERS . deflt ( ) ) ;
2011-04-08 23:15:10 +02:00
bmk_row . put ( b . key ( ) , YMarkUtil . keySetToString ( newSet ) ) ;
} else {
2011-04-18 23:42:14 +02:00
bmk_row . put ( b . key ( ) , bmk . get ( b . key ( ) ) ) ;
2011-04-08 23:15:10 +02:00
}
} else {
2011-04-18 23:42:14 +02:00
bmk_row . put ( b . key ( ) , bmk_row . get ( b . key ( ) , b . deflt ( ) ) ) ;
2011-04-08 23:15:10 +02:00
}
2011-06-22 01:10:50 +02:00
break ;
2011-04-08 23:15:10 +02:00
default :
if ( bmk . containsKey ( b . key ( ) ) ) {
2011-04-18 23:42:14 +02:00
bmk_row . put ( b . key ( ) , bmk . get ( b . key ( ) ) ) ;
2011-04-08 23:15:10 +02:00
} else {
2011-04-18 23:42:14 +02:00
bmk_row . put ( b . key ( ) , bmk_row . get ( b . key ( ) , b . deflt ( ) ) ) ;
2011-04-08 23:15:10 +02:00
}
}
}
// update bmk_table
2011-06-22 01:10:50 +02:00
this . worktables . update ( bmk_table , bmk_row ) ;
2012-09-09 09:53:58 +02:00
try {
if ( this . worktables . hasIndex ( bmk_table ) )
this . worktables . getIndex ( bmk_table ) . update ( YMarkEntry . BOOKMARK . indexColumns ( ) , bmk_row ) ;
2013-07-17 18:31:30 +02:00
} catch ( final Exception e ) {
2012-09-09 09:53:58 +02:00
// nothing to do
}
2011-04-08 23:15:10 +02:00
}
2012-08-31 14:07:33 +02:00
this . dirty = true ;
2011-04-08 23:15:10 +02:00
}
}
}
2011-04-21 00:33:01 +02:00