+ this.storageFile.writeChars(str);\r
+ }\r
+\r
+ /**\r
+ * Checks whether end of file has been reached\r
+ * \r
+ * @return Whether lines are left to read\r
+ */\r
+ private boolean isEndOfFile () {\r
+ // Default is EOF\r
+ boolean isEof = true;\r
+\r
+ try {\r
+ isEof = (this.storageFile.getFilePointer() >= this.length());\r
+ } catch (final IOException ex) {\r
+ // Length cannot be determined\r
+ this.getLogger().catching(ex);\r
+ }\r
+\r
+ // Return status\r
+ this.getLogger().trace(MessageFormat.format("isEof={0} : EXIT!", isEof));\r
+ return isEof;\r
+ }\r
+\r
+ /**\r
+ * Reads the database file, if available, and adds all read lines into\r
+ * the list.\r
+ * \r
+ * @return A list with Contact instances\r
+ */\r
+ private List<Contact> readContactList () throws BadTokenException {\r
+ this.getLogger().trace("CALLED!");\r
+\r
+ // First rewind\r
+ this.rewind();\r
+\r
+ // Instance list\r
+ // @TODO The maximum length could be guessed from file size?\r
+ List<Contact> list = new ArrayList<>();\r
+\r
+ // Init variables\r
+ StringTokenizer tokenizer;\r
+ String line;\r
+\r
+ // Read all lines\r
+ while (!this.isEndOfFile()) {\r
+ // Then read a line\r
+ line = this.readLine();\r
+\r
+ // Debug message\r
+ this.getLogger().debug(MessageFormat.format("line={0}", line));\r
+\r
+ // Then tokenize it\r
+ // @TODO Move this into separate method\r
+ tokenizer = new StringTokenizer(line, ";");\r
+\r
+ // Count round\r
+ int count = 0;\r
+\r
+ // Init contact object\r
+ Contact contact = null;\r
+\r
+ // The tokens are now available, so get all\r
+ while (tokenizer.hasMoreElements()) {\r
+ // Get next token\r
+ String token = tokenizer.nextToken();\r
+\r
+ // Debug message\r
+ this.getLogger().debug(MessageFormat.format("token={0}", token));\r
+\r
+ // Verify token, it must have double-quotes on each side\r
+ if ((!token.startsWith("\"")) || (!token.endsWith("\""))) {\r
+ // Something bad was read\r
+ throw new BadTokenException(MessageFormat.format("Token {0} has not double-quotes on both ends.", token));\r
+ }\r
+\r
+ // All fine, so remove it\r
+ String strippedToken = token.substring(1, token.length() - 1);\r
+\r
+ // Is the string's content "null"?\r
+ if (strippedToken.equals("null")) {\r
+ // Debug message\r
+ this.getLogger().debug(MessageFormat.format("strippedToken={0} - NULL!", strippedToken));\r
+\r
+ // This needs to be set to null\r
+ strippedToken = null;\r
+ }\r
+\r
+ // Debug message\r
+ this.getLogger().debug(MessageFormat.format("strippedToken={0}", strippedToken));\r
+\r
+ // Init number/string data values\r
+ String strData = strippedToken;\r
+ Long num = null;\r
+ Boolean bool = null;\r
+ char gender = '?';\r
+ \r
+ // Now, let's try a number check, if no null\r
+ if (strippedToken != null) {\r
+ // Okay, no null, maybe the string bears a decimal number?\r
+ try {\r
+ num = Long.valueOf(strippedToken);\r
+\r
+ // Debug message\r
+ this.getLogger().debug(MessageFormat.format("strippedToken={0} - NUMBER!", strippedToken));\r
+ } catch (final NumberFormatException ex) {\r
+ // No number, then set default\r
+ num = null;\r
+ }\r
+ }\r
+ \r
+ // Now, let's try a boolean check, if no null\r
+ if ((strippedToken != null) && (num == null) && ((strippedToken.equals("true")) || (strippedToken.equals("false")))) {\r
+ // Debug message\r
+ this.getLogger().debug(MessageFormat.format("strippedToken={0} - BOOLEAN!", strippedToken));\r
+\r
+ // parseBoolean() is relaxed, so no exceptions\r
+ bool = Boolean.valueOf(strippedToken);\r
+ }\r
+ \r
+ // Now, let's try a boolean check, if no null\r
+ if ((strippedToken != null) && (num == null) && (bool == null) && ((strippedToken.equals("M")) || (strippedToken.equals("F")) || (strippedToken.equals("C")))) {\r
+ // Get first character\r
+ gender = strippedToken.charAt(0);\r
+ }\r
+\r
+ // Now it depends on the counter which position we need to check\r
+ switch (count) {\r
+ case 0: // isOwnContact\r
+ assert((bool instanceof Boolean));\r
+\r
+ // Is it own contact?\r
+ if (true == bool) {\r
+ // Own entry\r
+ contact = new UserContact();\r
+ } else {\r
+ // Other contact\r
+ contact = new BookContact();\r
+ }\r
+ break;\r
+\r
+ case 1: // Gender\r
+ assert(contact instanceof Contact) : "First token was not boolean";\r
+ assert(gender != '?') : "Gender is not detected.";\r
+\r
+ // Update data\r
+ contact.updateNameData(gender, null, null, null);\r
+ break;\r
+\r
+ default: // New data entry\r
+ this.getLogger().warn("Will not handle unknown data " + strippedToken + " at index " + count);\r
+ break;\r
+ }\r
+\r
+ // Increment counter for next round\r
+ count++;\r
+ }\r
+ }\r
+\r
+ // Return finished list\r
+ this.getLogger().trace(MessageFormat.format("list.size()={0} : EXIT!", list.size()));\r
+ return list;\r
+ }\r
+\r
+ /**\r
+ * Reads a line from file base\r
+ *\r
+ * @return Read line from file\r
+ */\r
+ private String readLine () {\r
+ // Init input\r
+ String input = null;\r
+\r
+ try {\r
+ input = this.storageFile.readLine();\r
+ } catch (IOException ex) {\r
+ this.getLogger().catching(ex);\r
+ }\r
+\r
+ // Return read string or null\r
+ return input;\r