EMMA Coverage Report (generated Tue Jun 26 14:54:12 CEST 2012)
[all classes][org.tomdroid.sync.sd]

COVERAGE SUMMARY FOR SOURCE FILE [SdCardSyncService.java]

nameclass, %method, %block, %line, %
SdCardSyncService.java25%  (1/4)21%  (5/24)5%   (19/385)8%   (7/83)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class SdCardSyncService$NotesFilter0%   (0/1)0%   (0/3)0%   (0/14)0%   (0/2)
SdCardSyncService$NotesFilter (SdCardSyncService): void 0%   (0/1)0%   (0/6)0%   (0/1)
SdCardSyncService$NotesFilter (SdCardSyncService, SdCardSyncService$1): void 0%   (0/1)0%   (0/4)0%   (0/1)
accept (File, String): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
     
class SdCardSyncService100% (1/1)29%  (5/17)12%  (19/158)25%  (7/28)
access$100 (SdCardSyncService, int, HashMap): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
access$1000 (SdCardSyncService, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
access$200 (SdCardSyncService, int, HashMap): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
access$300 (): Pattern 0%   (0/1)0%   (0/2)0%   (0/1)
access$400 (SdCardSyncService, int, HashMap): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
access$500 (SdCardSyncService, Note): void 0%   (0/1)0%   (0/4)0%   (0/1)
access$600 (SdCardSyncService, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
access$700 (SdCardSyncService, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
access$800 (SdCardSyncService): int 0%   (0/1)0%   (0/3)0%   (0/1)
access$900 (SdCardSyncService): int 0%   (0/1)0%   (0/3)0%   (0/1)
needsServer (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
sync (): void 0%   (0/1)0%   (0/98)0%   (0/19)
<static initializer> 100% (1/1)100% (5/5)100% (1/1)
SdCardSyncService (Activity, Handler): void 100% (1/1)100% (8/8)100% (3/3)
getDescription (): String 100% (1/1)100% (2/2)100% (1/1)
getName (): String 100% (1/1)100% (2/2)100% (1/1)
needsAuth (): boolean 100% (1/1)100% (2/2)100% (1/1)
     
class SdCardSyncService$10%   (0/1)100% (0/0)100% (0/0)100% (0/0)
     
class SdCardSyncService$Worker0%   (0/1)0%   (0/4)0%   (0/213)0%   (0/53)
SdCardSyncService$Worker (SdCardSyncService, File, boolean): void 0%   (0/1)0%   (0/21)0%   (0/6)
onWorkDone (): void 0%   (0/1)0%   (0/28)0%   (0/5)
readFile (): String 0%   (0/1)0%   (0/39)0%   (0/8)
run (): void 0%   (0/1)0%   (0/125)0%   (0/34)

1/*
2 * Tomdroid
3 * Tomboy on Android
4 * http://www.launchpad.net/tomdroid
5 * 
6 * Copyright 2009, 2010, 2011 Olivier Bilodeau <olivier@bottomlesspit.org>
7 * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org>
8 * Copyright 2010, Rodja Trappe <mail@rodja.net>
9 * 
10 * This file is part of Tomdroid.
11 * 
12 * Tomdroid is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 * 
17 * Tomdroid is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 * 
22 * You should have received a copy of the GNU General Public License
23 * along with Tomdroid.  If not, see <http://www.gnu.org/licenses/>.
24 */
25package org.tomdroid.sync.sd;
26 
27import java.io.File;
28import java.io.FileInputStream;
29import java.io.FilenameFilter;
30import java.io.IOException;
31import java.io.InputStreamReader;
32import java.io.Reader;
33import java.io.StringReader;
34import java.util.regex.Matcher;
35import java.util.regex.Pattern;
36 
37import javax.xml.parsers.SAXParser;
38import javax.xml.parsers.SAXParserFactory;
39 
40import org.tomdroid.Note;
41import org.tomdroid.sync.SyncService;
42import org.tomdroid.ui.Tomdroid;
43import org.tomdroid.util.ErrorList;
44import org.xml.sax.InputSource;
45import org.xml.sax.XMLReader;
46 
47import android.app.Activity;
48import android.os.Handler;
49import android.util.Log;
50import android.util.TimeFormatException;
51 
52public class SdCardSyncService extends SyncService {
53        
54        private int numberOfFilesToSync = 0;
55        
56        // regexp for <note-content..>...</note-content>
57        private static Pattern note_content = Pattern.compile("<note-content[^>]+>(.*)<\\/note-content>", Pattern.CASE_INSENSITIVE+Pattern.DOTALL);
58        
59        // logging related
60        private final static String TAG = "SdCardSyncService";
61        
62        public SdCardSyncService(Activity activity, Handler handler) {
63                super(activity, handler);
64        }
65        
66        @Override
67        public String getDescription() {
68                return "SD Card";
69        }
70 
71        @Override
72        public String getName() {
73                return "sdcard";
74        }
75 
76        @Override
77        public boolean needsServer() {
78                return false;
79        }
80        
81        @Override
82        public boolean needsAuth() {
83                return false;
84        }
85 
86        @Override
87        protected void sync() {
88 
89                setSyncProgress(0);
90 
91                // start loading local notes
92                if (Tomdroid.LOGGING_ENABLED) Log.v(TAG, "Loading local notes");
93                
94                File path = new File(Tomdroid.NOTES_PATH);
95                
96                if (!path.exists())
97                        path.mkdir();
98                
99                Log.i(TAG, "Path "+path+" exists: "+path.exists());
100                
101                // Check a second time, if not the most likely cause is the volume doesn't exist
102                if(!path.exists()) {
103                        if (Tomdroid.LOGGING_ENABLED) Log.w(TAG, "Couldn't create "+path);
104                        sendMessage(NO_SD_CARD);
105                        setSyncProgress(100);
106                        return;
107                }
108                
109                File[] fileList = path.listFiles(new NotesFilter());
110                numberOfFilesToSync  = fileList.length;
111                
112                // If there are no notes, warn the UI through an empty message
113                if (fileList == null || fileList.length == 0) {
114                        if (Tomdroid.LOGGING_ENABLED) Log.i(TAG, "There are no notes in "+path);
115                        sendMessage(PARSING_NO_NOTES);
116                        setSyncProgress(100);
117                        return;
118                }
119                
120                // every but the last note
121                for(int i = 0; i < fileList.length-1; i++) {
122                        // TODO better progress reporting from within the workers
123                        
124                        // give a filename to a thread and ask to parse it
125                        syncInThread(new Worker(fileList[i], false));
126        }
127                
128                // last task, warn it so it'll warn UI when done
129                syncInThread(new Worker(fileList[fileList.length-1], true));
130        }
131        
132        /**
133         * Simple filename filter that grabs files ending with .note
134         * TODO move into its own static class in a util package
135         */
136        private class NotesFilter implements FilenameFilter {
137                public boolean accept(File dir, String name) {
138                        return (name.endsWith(".note"));
139                }
140        }
141        
142        /**
143         * The worker spawns a new note, parse the file its being given by the executor.
144         */
145        // TODO change type to callable to be able to throw exceptions? (if you throw make sure to display an alert only once)
146        // http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Callable.html
147        private class Worker implements Runnable {
148                
149                // the note to be loaded and parsed
150                private Note note = new Note();
151                private File file;
152                private boolean isLast;
153                final char[] buffer = new char[0x1000];
154                
155                public Worker(File f, boolean isLast) {
156                        file = f;
157                        this.isLast = isLast;
158                }
159 
160                public void run() {
161                        
162                        note.setFileName(file.getAbsolutePath());
163                        // the note guid is not stored in the xml but in the filename
164                        note.setGuid(file.getName().replace(".note", ""));
165                        
166                        // Try reading the file first
167                        String contents = "";
168                        try {
169                                contents = readFile();
170                        } catch (IOException e) {
171                                e.printStackTrace();
172                                if (Tomdroid.LOGGING_ENABLED) Log.w(TAG, "Something went wrong trying to read the note");
173                                sendMessage(PARSING_FAILED, ErrorList.createError(note, e));
174                                onWorkDone();
175                                return;
176                        }
177 
178                        try {
179                                // Parsing
180                            // XML 
181                            // Get a SAXParser from the SAXPArserFactory
182                        SAXParserFactory spf = SAXParserFactory.newInstance();
183                        SAXParser sp = spf.newSAXParser();
184                
185                        // Get the XMLReader of the SAXParser we created
186                        XMLReader xr = sp.getXMLReader();
187 
188                        // Create a new ContentHandler, send it this note to fill and apply it to the XML-Reader
189                        NoteHandler xmlHandler = new NoteHandler(note);
190                        xr.setContentHandler(xmlHandler);
191 
192                        // Create the proper input source
193                        StringReader sr = new StringReader(contents);
194                        InputSource is = new InputSource(sr);
195                        
196                                if (Tomdroid.LOGGING_ENABLED) Log.d(TAG, "parsing note");
197                                xr.parse(is);
198 
199                        // TODO wrap and throw a new exception here
200                        } catch (Exception e) {
201                                e.printStackTrace();
202                                if(e instanceof TimeFormatException) Log.e(TAG, "Problem parsing the note's date and time");
203                                sendMessage(PARSING_FAILED, ErrorList.createErrorWithContents(note, e, contents));
204                                onWorkDone();
205                                return;
206                        }
207 
208                        // extract the <note-content..>...</note-content>
209                        if (Tomdroid.LOGGING_ENABLED) Log.d(TAG, "retrieving what is inside of note-content");
210                        
211                        // FIXME here we are re-reading the whole note just to grab note-content out, there is probably a best way to do this (I'm talking to you xmlpull.org!)
212                        Matcher m = note_content.matcher(contents);
213                        if (m.find()) {
214                                note.setXmlContent(m.group(1));
215                        } else {
216                                if (Tomdroid.LOGGING_ENABLED) Log.w(TAG, "Something went wrong trying to grab the note-content out of a note");
217                                sendMessage(PARSING_FAILED, ErrorList.createErrorWithContents(note, "Something went wrong trying to grab the note-content out of a note", contents));
218                                onWorkDone();
219                                return;
220                        }
221                        
222                        insertNote(note);
223                        onWorkDone();
224                }
225                
226                private String readFile() throws IOException {
227                        StringBuilder out = new StringBuilder();
228                        
229                        int read;
230                        Reader reader = new InputStreamReader(new FileInputStream(file), "UTF-8");
231                        
232                        do {
233                          read = reader.read(buffer, 0, buffer.length);
234                          if (read > 0) {
235                            out.append(buffer, 0, read);
236                          }
237                        }
238                        while (read >= 0);
239                        
240                        reader.close();
241                        return out.toString();
242                }
243                
244                private void onWorkDone(){
245                        if (isLast) {
246                                setSyncProgress(100);
247                                sendMessage(PARSING_COMPLETE);
248                        }
249                        else
250                                setSyncProgress((int) (getSyncProgress() + 100.0 / numberOfFilesToSync));                        
251                }
252        }
253}

[all classes][org.tomdroid.sync.sd]
EMMA 0.0.0 (unsupported private build) (C) Vladimir Roubtsov