/*******************************************************************************
* Copyright (c) 2007-2010, G. Weirich and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
*
*******************************************************************************/
package ch.elexis.notes;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import ch.elexis.core.constants.StringConstants;
import ch.elexis.data.PersistentObject;
import ch.elexis.data.Query;
import ch.rgw.tools.ExHandler;
import ch.rgw.tools.StringTool;
import ch.rgw.tools.TimeTool;
import ch.rgw.tools.VersionInfo;
/**
* A Note is an arbitrary Text or BLOB with a name and optional keywords. A Note can consist of or
* contain external links to files in the file system or URLs. Notes are stored hierarchically in a
* tree-like structure (which ist mapped to a flat database table via a "parent"-field).
*
* @author gerry
*
*/
public class Note extends PersistentObject {
public static final String FLD_MIMETYPE = "mimetype"; //$NON-NLS-1$
public static final String FLD_KEYWORDS = "keywords"; //$NON-NLS-1$
public static final String FLD_REFS = "refs"; //$NON-NLS-1$
public static final String FLD_CONTENTS = "Contents"; //$NON-NLS-1$
public static final String FLD_TITLE = "Title"; //$NON-NLS-1$
private static final String FLD_PARENT = "Parent"; //$NON-NLS-1$
private static final String TABLENAME = "CH_ELEXIS_NOTES"; //$NON-NLS-1$
private static final String DBVERSION = "0.3.2"; //$NON-NLS-1$
/**
* The String that defines the database. Will be used only once at first start of this plugin
*/
private static final String create =
"CREATE TABLE " + TABLENAME + " (" + "ID VARCHAR(25)," + "lastupdate BIGINT," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ "deleted CHAR(1) default '0'," + "Parent VARCHAR(25)," + "Title VARCHAR(80)," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ "Date CHAR(8)," + "Contents BLOB," + "keywords VARCHAR(255)," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ "mimetype VARCHAR(80)," + "refs TEXT);" + "INSERT INTO " + TABLENAME //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ " (ID,Title,Parent) VALUES('1','" + DBVERSION + "','xxx');"; //$NON-NLS-1$ //$NON-NLS-2$
/**
* Update to Version 0.31
*/
private static final String upd031 =
"ALTER TABLE " + TABLENAME + " ADD keywords VARCHAR(255);" + "ALTER TABLE " + TABLENAME //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ " ADD mimetype VARCHAR(80);"; //$NON-NLS-1$
/**
* Update to Version 0.32
*/
private static final String upd032 = "ALTER TABLE " + TABLENAME + " ADD lastupdate BIGINT;"; //$NON-NLS-1$ //$NON-NLS-2$
/**
* Initaialization: Create the table mappings (@see PersistentObject), check the version and
* create or update the table if necessary
*/
static {
addMapping(TABLENAME, FLD_PARENT, FLD_TITLE, FLD_CONTENTS, "Datum=S:D:Date", FLD_REFS,
FLD_KEYWORDS, FLD_MIMETYPE);
Note start = load("1"); //$NON-NLS-1$
if (!start.exists()) {
createOrModifyTable(create);
} else {
VersionInfo vi = new VersionInfo(start.get(FLD_TITLE));
if (vi.isOlder(DBVERSION)) {
if (vi.isOlder("0.2.0")) { //$NON-NLS-1$
getConnection().exec(
"ALTER TABLE " + TABLENAME + " ADD deleted CHAR(1) default '0';"); //$NON-NLS-1$ //$NON-NLS-2$
}
if (vi.isOlder("0.3.1")) { //$NON-NLS-1$
createOrModifyTable(upd031);
}
if (vi.isOlder("0.3.2")) { //$NON-NLS-1$
createOrModifyTable(upd032);
}
start.set(FLD_TITLE, DBVERSION);
}
}
}
/**
* Create a new Note with text content
*
* @param parent
* the parent note or null if this is a top level note
* @param title
* a Title for this note
* @param text
* the text content of this note
*/
public Note(Note parent, String title, String text){
create(null);
set(new String[] {
FLD_TITLE, FLD_DATE, FLD_MIMETYPE
}, title, new TimeTool().toString(TimeTool.DATE_GER), "text/plain"); //$NON-NLS-1$
try {
setContent(text.getBytes("utf-8")); //$NON-NLS-1$
} catch (UnsupportedEncodingException e) {
ExHandler.handle(e);
// should never happen
}
if (parent != null) {
set(FLD_PARENT, parent.getId());
}
}
/**
* Create a new Note with binary content
*
* @param parent
* the parent note or null if this is a top level note
* @param title
* a Title for this note
* @param contents
* the contents of this note in
* @param mimettype
* the mimetype of the contents
*/
public Note(Note parent, String title, byte[] contents, String mimetype){
create(null);
set(new String[] {
FLD_TITLE, FLD_DATE, FLD_MIMETYPE
}, title, new TimeTool().toString(TimeTool.DATE_GER), mimetype);
setContent(contents);
if (parent != null) {
set(FLD_PARENT, parent.getId());
}
}
/**
* find the parent note of this note
*
* @return the parent note or null if this is a top level note.
*/
public Note getParent(){
String pid = get(FLD_PARENT);
if (pid == null) {
return null;
}
Note p = Note.load(pid);
return p;
}
/**
* find the children of this note
*
* @return a list of all Notes that are children of the current note. The list might me empty
* but is never null.
*/
public List<Note> getChildren(){
Query<Note> qbe = new Query<Note>(Note.class);
qbe.add(FLD_PARENT, Query.EQUALS, getId());
return qbe.execute();
}
/**
* Set new binary content to the current note. Any old content will be overwritten.
*
* @param cnt
* the new content
*/
public void setContent(byte[] cnt){
setBinary(FLD_CONTENTS, cnt);
set(FLD_DATE, new TimeTool().toString(TimeTool.DATE_GER));
}
/**
* retrieve the content of this note
*
* @return a byte[] containing the data for this note's content
*/
public byte[] getContent(){
return getBinary(FLD_CONTENTS);
}
/**
* retrieve the keywords that are associated with this note.
*
* @return a String with a comma separated list of keywords that may be empty but is never null
*/
public String getKeywords(){
return checkNull(get(FLD_KEYWORDS));
}
/**
* Enter keywords for this note
*
* @param kw
* a string with a comma separated list of keywords (at most 250 chars)
*/
public void setKeywords(String kw){
set(FLD_KEYWORDS, StringTool.limitLength(kw.toLowerCase(), 250));
}
/**
* Return externals references associated with this Note
*
* @return a List with urls of external refs
*/
public List<String> getRefs(){
String all = get(FLD_REFS);
if (StringTool.isNothing(all)) {
return new ArrayList<String>();
}
return StringTool.splitAL(all, StringConstants.COMMA);
}
/**
* Add a new external ref
*
* @param ref
* a string representing an URL
*/
public void addRef(String ref){
List<String> refs = getRefs();
refs.add(ref);
set(FLD_REFS, StringTool.join(refs, StringConstants.COMMA));
}
/**
* remove an external reference
*
* @param ref
* the reference to remove
*/
public void removeRef(String ref){
List<String> refs = getRefs();
refs.remove(ref);
set(FLD_REFS, StringTool.join(refs, StringConstants.COMMA));
}
@Override
public String getLabel(){
return get(FLD_TITLE);
}
@Override
public boolean delete(){
Query<Note> qbe = new Query<Note>(Note.class);
qbe.add(FLD_PARENT, Query.EQUALS, getId());
List<Note> list = qbe.execute();
for (Note note : list) {
note.delete();
}
return super.delete();
}
@Override
protected String getTableName(){
return TABLENAME;
}
public static Note load(String id){
return new Note(id);
}
protected Note(String id){
super(id);
}
protected Note(){}
}