| 1 | /* |
| 2 | * Tomdroid |
| 3 | * Tomboy on Android |
| 4 | * http://www.launchpad.net/tomdroid |
| 5 | * |
| 6 | * Copyright 2008, 2009, 2010, 2011 Olivier Bilodeau <olivier@bottomlesspit.org> |
| 7 | * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
| 8 | * |
| 9 | * This file is part of Tomdroid. |
| 10 | * |
| 11 | * Tomdroid is free software: you can redistribute it and/or modify |
| 12 | * it under the terms of the GNU General Public License as published by |
| 13 | * the Free Software Foundation, either version 3 of the License, or |
| 14 | * (at your option) any later version. |
| 15 | * |
| 16 | * Tomdroid is distributed in the hope that it will be useful, |
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 19 | * GNU General Public License for more details. |
| 20 | * |
| 21 | * You should have received a copy of the GNU General Public License |
| 22 | * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
| 23 | */ |
| 24 | package org.tomdroid; |
| 25 | |
| 26 | import java.util.regex.Matcher; |
| 27 | import java.util.regex.Pattern; |
| 28 | |
| 29 | import org.json.JSONArray; |
| 30 | import org.json.JSONObject; |
| 31 | import org.tomdroid.util.NoteContentBuilder; |
| 32 | import org.tomdroid.util.XmlUtils; |
| 33 | |
| 34 | import android.os.Handler; |
| 35 | import android.text.SpannableStringBuilder; |
| 36 | import android.text.format.Time; |
| 37 | import android.util.Log; |
| 38 | import android.util.TimeFormatException; |
| 39 | |
| 40 | public class Note { |
| 41 | |
| 42 | // Static references to fields (used in Bundles, ContentResolvers, etc.) |
| 43 | public static final String ID = "_id"; |
| 44 | public static final String GUID = "guid"; |
| 45 | public static final String TITLE = "title"; |
| 46 | public static final String MODIFIED_DATE = "modified_date"; |
| 47 | public static final String URL = "url"; |
| 48 | public static final String FILE = "file"; |
| 49 | public static final String TAGS = "tags"; |
| 50 | public static final String NOTE_CONTENT = "content"; |
| 51 | |
| 52 | // Logging info |
| 53 | private static final String TAG = "Note"; |
| 54 | |
| 55 | // Notes constants |
| 56 | // TODO this is a weird yellow that was usable for the android emulator, I must confirm this for real usage |
| 57 | public static final int NOTE_HIGHLIGHT_COLOR = 0xFFFFFF77; |
| 58 | public static final String NOTE_MONOSPACE_TYPEFACE = "monospace"; |
| 59 | public static final float NOTE_SIZE_SMALL_FACTOR = 1.0f; |
| 60 | public static final float NOTE_SIZE_LARGE_FACTOR = 1.5f; |
| 61 | public static final float NOTE_SIZE_HUGE_FACTOR = 1.8f; |
| 62 | |
| 63 | // Members |
| 64 | private SpannableStringBuilder noteContent; |
| 65 | private String xmlContent; |
| 66 | private String url; |
| 67 | private String fileName; |
| 68 | private String title; |
| 69 | private String tags; |
| 70 | private Time lastChangeDate; |
| 71 | private int dbId; |
| 72 | // TODO before guid were of the UUID object type, now they are simple strings |
| 73 | // but at some point we probably need to validate their uniqueness (per note collection or universe-wide?) |
| 74 | private String guid; |
| 75 | |
| 76 | // Date converter pattern (remove extra sub milliseconds from datetime string) |
| 77 | // ex: will strip 3020 in 2010-01-23T12:07:38.7743020-05:00 |
| 78 | private static final Pattern dateCleaner = Pattern.compile( |
| 79 | "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3})" + // matches: 2010-01-23T12:07:38.774 |
| 80 | ".+" + // matches what we are getting rid of |
| 81 | "([-\\+]\\d{2}:\\d{2})"); // matches timezone (-xx:xx or +xx:xx) |
| 82 | |
| 83 | public Note() { |
| 84 | tags = new String(); |
| 85 | } |
| 86 | |
| 87 | public Note(JSONObject json) { |
| 88 | |
| 89 | // These methods return an empty string if the key is not found |
| 90 | setTitle(XmlUtils.unescape(json.optString("title"))); |
| 91 | setGuid(json.optString("guid")); |
| 92 | setLastChangeDate(json.optString("last-change-date")); |
| 93 | setXmlContent(json.optString("note-content")); |
| 94 | JSONArray jtags = json.optJSONArray("tags"); |
| 95 | String tag; |
| 96 | tags = new String(); |
| 97 | if (jtags != null) { |
| 98 | for (int i = 0; i < jtags.length(); i++ ) { |
| 99 | tag = jtags.optString(i); |
| 100 | tags += tag + ","; |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | public String getTags() { |
| 106 | return tags; |
| 107 | } |
| 108 | |
| 109 | public String getUrl() { |
| 110 | return url; |
| 111 | } |
| 112 | |
| 113 | public void setUrl(String url) { |
| 114 | this.url = url; |
| 115 | } |
| 116 | |
| 117 | public String getFileName() { |
| 118 | return fileName; |
| 119 | } |
| 120 | |
| 121 | public void setFileName(String fileName) { |
| 122 | this.fileName = fileName; |
| 123 | } |
| 124 | |
| 125 | public String getTitle() { |
| 126 | return title; |
| 127 | } |
| 128 | |
| 129 | public void setTitle(String title) { |
| 130 | this.title = title; |
| 131 | } |
| 132 | |
| 133 | public Time getLastChangeDate() { |
| 134 | return lastChangeDate; |
| 135 | } |
| 136 | |
| 137 | public void setLastChangeDate(Time lastChangeDate) { |
| 138 | this.lastChangeDate = lastChangeDate; |
| 139 | } |
| 140 | |
| 141 | public void setLastChangeDate(String lastChangeDateStr) throws TimeFormatException { |
| 142 | |
| 143 | // regexp out the sub-milliseconds from tomboy's datetime format |
| 144 | // Normal RFC 3339 format: 2008-10-13T16:00:00.000-07:00 |
| 145 | // Tomboy's (C# library) format: 2010-01-23T12:07:38.7743020-05:00 |
| 146 | Matcher m = dateCleaner.matcher(lastChangeDateStr); |
| 147 | if (m.find()) { |
| 148 | Log.d(TAG, "I had to clean out extra sub-milliseconds from the date"); |
| 149 | lastChangeDateStr = m.group(1)+m.group(2); |
| 150 | Log.v(TAG, "new date: "+lastChangeDateStr); |
| 151 | } |
| 152 | |
| 153 | lastChangeDate = new Time(); |
| 154 | lastChangeDate.parse3339(lastChangeDateStr); |
| 155 | } |
| 156 | |
| 157 | public int getDbId() { |
| 158 | return dbId; |
| 159 | } |
| 160 | |
| 161 | public void setDbId(int id) { |
| 162 | this.dbId = id; |
| 163 | } |
| 164 | |
| 165 | public String getGuid() { |
| 166 | return guid; |
| 167 | } |
| 168 | |
| 169 | public void setGuid(String guid) { |
| 170 | this.guid = guid; |
| 171 | } |
| 172 | |
| 173 | // TODO: should this handler passed around evolve into an observer pattern? |
| 174 | public SpannableStringBuilder getNoteContent(Handler handler) { |
| 175 | |
| 176 | // TODO not sure this is the right place to do this |
| 177 | noteContent = new NoteContentBuilder().setCaller(handler).setInputSource(xmlContent).build(); |
| 178 | return noteContent; |
| 179 | } |
| 180 | |
| 181 | public String getXmlContent() { |
| 182 | return xmlContent; |
| 183 | } |
| 184 | |
| 185 | public void setXmlContent(String xmlContent) { |
| 186 | this.xmlContent = xmlContent; |
| 187 | } |
| 188 | |
| 189 | @Override |
| 190 | public String toString() { |
| 191 | |
| 192 | return new String("Note: "+ getTitle() + " (" + getLastChangeDate() + ")"); |
| 193 | } |
| 194 | |
| 195 | } |