diff --git a/src/net/java/sip/communicator/service/history/History.java b/src/net/java/sip/communicator/service/history/History.java index b71a1e545..fef284dae 100644 --- a/src/net/java/sip/communicator/service/history/History.java +++ b/src/net/java/sip/communicator/service/history/History.java @@ -11,28 +11,29 @@ /** * @author Alexander Pelov */ -public interface History { - - /** - * @return Returns an object which can be used to read and query - * this history. - */ - HistoryReader getReader(); - - /** - * @return Returns an object which can be used to append records to - * this history. - */ - HistoryWriter getWriter(); - - /** - * @return Returns the ID of this history. - */ - HistoryID getID(); - - /** - * @return Returns the structure of the history records in this history. - */ - HistoryRecordStructure getHistoryRecordsStructure(); - +public interface History +{ + + /** + * @return Returns an object which can be used to read and query + * this history. + */ + HistoryReader getReader(); + + /** + * @return Returns an object which can be used to append records to + * this history. + */ + HistoryWriter getWriter(); + + /** + * @return Returns the ID of this history. + */ + HistoryID getID(); + + /** + * @return Returns the structure of the history records in this history. + */ + HistoryRecordStructure getHistoryRecordsStructure(); + } diff --git a/src/net/java/sip/communicator/service/history/HistoryID.java b/src/net/java/sip/communicator/service/history/HistoryID.java index 0ad0bb192..527b03e92 100644 --- a/src/net/java/sip/communicator/service/history/HistoryID.java +++ b/src/net/java/sip/communicator/service/history/HistoryID.java @@ -8,207 +8,242 @@ /** * Object used to uniquely identify a group of history records. - * + * * @author Alexander Pelov */ -public class HistoryID { - - private String[] id; - - private String stringRepresentation; - - private int hashCode; - - private HistoryID(String[] id) { - this.id = id; - - StringBuffer buff = new StringBuffer(); - for(int i = 0; i < id.length; i++) { - if(i > 0) buff.append(' '); - buff.append(this.id[i]); - } - - this.stringRepresentation = buff.toString(); - this.hashCode = this.stringRepresentation.hashCode(); - } - - /** - * Create a HistoryID from a raw ID. You can pass any kind of - * strings and they will be safely converted to valid IDs. - */ - public static HistoryID createFromRawID(String[] rawid) { - // TODO: Validate: Assert.assertNonNull(rawid, "Parameter RAWID should be non-null"); - // TODO: Validate: Assert.assertTrue(rawid.length > 0, "RAWID.length should be > 0"); - - String[] id = new String[rawid.length]; - for(int i = 0; i < rawid.length; i++) { - id[i] = HistoryID.readableHash(rawid[i]); - } - - return new HistoryID(id); - } - - /** - * Create a HistoryID from a valid ID. You should pass only - * valid IDs (ones produced from readableHash). - * - * @throws IllegalArgumentException Thrown if a string from the ID is not - * valid an exception. - */ - public static HistoryID createFromID(String[] id) - throws IllegalArgumentException - { - // TODO: Validate: Assert.assertNonNull(id, "Parameter ID should be non-null"); - // TODO: Validate: Assert.assertTrue(id.length > 0, "ID.length should be > 0"); - - for(int i = 0; i < id.length; i++) { - if(!HistoryID.isIDValid(id[i])) { - throw new IllegalArgumentException("Not a valid ID: " + id[i]); - } - } - - String[] newID = new String[id.length]; - System.arraycopy(id, 0, newID, 0, id.length); - return new HistoryID(newID); - } - - public String[] getID() { - return this.id; - } - - public String toString() { - return this.stringRepresentation; - } - - public int hashCode() { - return this.hashCode; - } - - public boolean equals(Object obj) { - boolean eq = false; - - if(obj instanceof HistoryID) { - String[] id = ((HistoryID)obj).id; - - if(this.id.length == id.length) { - for(int i = 0; i < id.length; i++) { - String s1 = id[i]; - String s2 = this.id[i]; - - if(!((s1 == s2) || (s1 != null && s1.equals(s2)))) { - eq = false; - break; - } - } - } - } - - return eq; - } - - /** - * An one-way function returning a "human readable" containing no special - * characters. All characters _, a-z, A-Z, 0-9 are kept unchainged. - * All other are replaced with _ and the word is postfixed with - * %HASHCODE, where HASHCODE is the hexadecimal hash value of the - * original string. If there are no special characters the word is - * not postfixed. - * - * Note: This method does not use URLEncoder, because in url-encoding - * the * sign is considered as "safe". - * - * @param rawString The string to be hashed. - * @return The human-readable hash. - */ - public static String readableHash(String rawString) { - StringBuffer encodedString = new StringBuffer(rawString); - boolean addHash = false; - - for(int i = 0; i < encodedString.length(); i++) { - if(HistoryID.isSpecialChar(encodedString.charAt(i))) { - addHash = true; - encodedString.setCharAt(i, '_'); - } - } - - if(addHash) { - encodedString.append('%'); - encodedString.append(Integer.toHexString(rawString.hashCode())); - } - - return encodedString.toString(); - } - - /** - * Tests if an ID is valid. - */ - private static boolean isIDValid(String id) { - boolean isValid = true; - - int pos = id.indexOf('%'); - if(pos < 0) { - // There is no % in the id. In order to be valid all characters - // should be non-special - isValid = !hasSpecialChar(id); - } else { - // There is a % sign in the id. In order to be valid it has - // to be in the form X..X%Y..Y, where there should be no - // special characters in X..X, and Y..Y should be a hexadecimal - // number - if(pos+1 < id.length()) { - String start = id.substring(0, pos); - String end = id.substring(pos+1); - - // Check X..X - isValid = !hasSpecialChar(start); - if(isValid) { - // OK; Check Y..Y - try { - Integer.parseInt(end, 16); - // OK - isValid = true; - } catch(Exception e) { - // Not OK - isValid = false; - } - } - } else { - // The % sign is in the beginning - bad ID. - isValid = false; - } - } - - return isValid; - } - - /** - * Tests if a character is a special one. A character is special - * if it is not in the range _, a-z, A-Z, 0-9. - * - * @param c The character to test. - * @return Returns true if the character is special. False otherwise. - */ - private static boolean isSpecialChar(char c) { - return (c != '_') && - (c < 'A' || c > 'Z') && - (c < 'a' || c > 'z') && - (c < '0' || c > '9'); - } - - /** - * Tests there is a special character in a string. - */ - private static boolean hasSpecialChar(String str) { - boolean hasSpecialChar = false; - - for(int i = 0; i < str.length(); i++) { - if(isSpecialChar(str.charAt(i))) { - hasSpecialChar = false; - break; - } - } - - return hasSpecialChar; - } - +public class HistoryID +{ + + private String[] id; + + private String stringRepresentation; + + private int hashCode; + + private HistoryID(String[] id) + { + this.id = id; + + StringBuffer buff = new StringBuffer(); + for (int i = 0; i < id.length; i++) + { + if (i > 0) + buff.append(' '); + buff.append(this.id[i]); + } + + this.stringRepresentation = buff.toString(); + this.hashCode = this.stringRepresentation.hashCode(); + } + + /** + * Create a HistoryID from a raw ID. You can pass any kind of + * strings and they will be safely converted to valid IDs. + */ + public static HistoryID createFromRawID(String[] rawid) + { + // TODO: Validate: Assert.assertNonNull(rawid, "Parameter RAWID should be non-null"); + // TODO: Validate: Assert.assertTrue(rawid.length > 0, "RAWID.length should be > 0"); + + String[] id = new String[rawid.length]; + for (int i = 0; i < rawid.length; i++) + { + id[i] = HistoryID.readableHash(rawid[i]); + } + + return new HistoryID(id); + } + + /** + * Create a HistoryID from a valid ID. You should pass only + * valid IDs (ones produced from readableHash). + * + * @throws IllegalArgumentException Thrown if a string from the ID is not + * valid an exception. + */ + public static HistoryID createFromID(String[] id) throws + IllegalArgumentException + { + // TODO: Validate: Assert.assertNonNull(id, "Parameter ID should be non-null"); + // TODO: Validate: Assert.assertTrue(id.length > 0, "ID.length should be > 0"); + + for (int i = 0; i < id.length; i++) + { + if (!HistoryID.isIDValid(id[i])) + { + throw new IllegalArgumentException("Not a valid ID: " + id[i]); + } + } + + String[] newID = new String[id.length]; + System.arraycopy(id, 0, newID, 0, id.length); + return new HistoryID(newID); + } + + public String[] getID() + { + return this.id; + } + + public String toString() + { + return this.stringRepresentation; + } + + public int hashCode() + { + return this.hashCode; + } + + public boolean equals(Object obj) + { + boolean eq = false; + + if (obj instanceof HistoryID) + { + String[] id = ( (HistoryID) obj).id; + + if (this.id.length == id.length) + { + for (int i = 0; i < id.length; i++) + { + String s1 = id[i]; + String s2 = this.id[i]; + + if (! ( (s1 == s2) || (s1 != null && s1.equals(s2)))) + { + eq = false; + break; + } + } + } + } + + return eq; + } + + /** + * An one-way function returning a "human readable" containing no special + * characters. All characters _, a-z, A-Z, 0-9 are kept unchainged. + * All other are replaced with _ and the word is postfixed with + * %HASHCODE, where HASHCODE is the hexadecimal hash value of the + * original string. If there are no special characters the word is + * not postfixed. + * + * Note: This method does not use URLEncoder, because in url-encoding + * the * sign is considered as "safe". + * + * @param rawString The string to be hashed. + * @return The human-readable hash. + */ + public static String readableHash(String rawString) + { + StringBuffer encodedString = new StringBuffer(rawString); + boolean addHash = false; + + for (int i = 0; i < encodedString.length(); i++) + { + if (HistoryID.isSpecialChar(encodedString.charAt(i))) + { + addHash = true; + encodedString.setCharAt(i, '_'); + } + } + + if (addHash) + { + encodedString.append('%'); + encodedString.append(Integer.toHexString(rawString.hashCode())); + } + + return encodedString.toString(); + } + + /** + * Tests if an ID is valid. + */ + private static boolean isIDValid(String id) + { + boolean isValid = true; + + int pos = id.indexOf('%'); + if (pos < 0) + { + // There is no % in the id. In order to be valid all characters + // should be non-special + isValid = !hasSpecialChar(id); + } + else + { + // There is a % sign in the id. In order to be valid it has + // to be in the form X..X%Y..Y, where there should be no + // special characters in X..X, and Y..Y should be a hexadecimal + // number + if (pos + 1 < id.length()) + { + String start = id.substring(0, pos); + String end = id.substring(pos + 1); + + // Check X..X + isValid = !hasSpecialChar(start); + if (isValid) + { + // OK; Check Y..Y + try + { + Integer.parseInt(end, 16); + // OK + isValid = true; + } + catch (Exception e) + { + // Not OK + isValid = false; + } + } + } + else + { + // The % sign is in the beginning - bad ID. + isValid = false; + } + } + + return isValid; + } + + /** + * Tests if a character is a special one. A character is special + * if it is not in the range _, a-z, A-Z, 0-9. + * + * @param c The character to test. + * @return Returns true if the character is special. False otherwise. + */ + private static boolean isSpecialChar(char c) + { + return (c != '_') && + (c < 'A' || c > 'Z') && + (c < 'a' || c > 'z') && + (c < '0' || c > '9'); + } + + /** + * Tests there is a special character in a string. + */ + private static boolean hasSpecialChar(String str) + { + boolean hasSpecialChar = false; + + for (int i = 0; i < str.length(); i++) + { + if (isSpecialChar(str.charAt(i))) + { + hasSpecialChar = false; + break; + } + } + + return hasSpecialChar; + } + } diff --git a/src/net/java/sip/communicator/service/history/HistoryService.java b/src/net/java/sip/communicator/service/history/HistoryService.java index 188f1d565..6c74b1c84 100644 --- a/src/net/java/sip/communicator/service/history/HistoryService.java +++ b/src/net/java/sip/communicator/service/history/HistoryService.java @@ -20,43 +20,43 @@ * * @author Alexander Pelov */ -public interface HistoryService { +public interface HistoryService +{ - /** - * Returns the IDs of all existing histories. - * - * @return An iterator to a list of IDs. - */ - Iterator getExistingIDs(); + /** + * Returns the IDs of all existing histories. + * + * @return An iterator to a list of IDs. + */ + Iterator getExistingIDs(); - /** - * Returns the history associated with this ID. - * - * @param id The ID of the history. - * @return Returns the history with this ID. - * @throws IllegalArgumentException Thrown if there is no such history. - */ - History getHistory(HistoryID id) - throws IllegalArgumentException; + /** + * Returns the history associated with this ID. + * + * @param id The ID of the history. + * @return Returns the history with this ID. + * @throws IllegalArgumentException Thrown if there is no such history. + */ + History getHistory(HistoryID id) throws IllegalArgumentException; - /** - * Tests if a history with the given ID exists. - * - * @param id The ID to test. - * @return True if a history with this ID exists. False otherwise. - */ - boolean isHistoryExisting(HistoryID id); + /** + * Tests if a history with the given ID exists. + * + * @param id The ID to test. + * @return True if a history with this ID exists. False otherwise. + */ + boolean isHistoryExisting(HistoryID id); - /** - * Creates a new history for this ID. - * - * @param id The ID of the history to be created. - * @param recordStructure The structure of the data. - * @return Returns the history with this ID. - * @throws IllegalArgumentException Thrown if such history already exists. - * @throws IOException Thrown if the history could not be created due to - * a IO error. - */ - History createHistory(HistoryID id, HistoryRecordStructure recordStructure) - throws IllegalArgumentException, IOException; + /** + * Creates a new history for this ID. + * + * @param id The ID of the history to be created. + * @param recordStructure The structure of the data. + * @return Returns the history with this ID. + * @throws IllegalArgumentException Thrown if such history already exists. + * @throws IOException Thrown if the history could not be created due to + * a IO error. + */ + History createHistory(HistoryID id, HistoryRecordStructure recordStructure) throws + IllegalArgumentException, IOException; } diff --git a/src/net/java/sip/communicator/service/history/HistoryWriter.java b/src/net/java/sip/communicator/service/history/HistoryWriter.java index cba2bd154..3fbadd196 100644 --- a/src/net/java/sip/communicator/service/history/HistoryWriter.java +++ b/src/net/java/sip/communicator/service/history/HistoryWriter.java @@ -13,24 +13,25 @@ /** * @author Alexander Pelov */ -public interface HistoryWriter { - - /** - * Stores the passed record complying with the historyRecordStructure. - * - * @param record The record to be added. - * - * @throws IOException - */ - void addRecord(HistoryRecord record) throws IOException; - - /** - * Stores the passed propertyValues complying with the historyRecordStructure. - * - * @param propertyValues The values of the record. - * - * @throws IOException - */ - void addRecord(String[] propertyValues) throws IOException; - +public interface HistoryWriter +{ + + /** + * Stores the passed record complying with the historyRecordStructure. + * + * @param record The record to be added. + * + * @throws IOException + */ + void addRecord(HistoryRecord record) throws IOException; + + /** + * Stores the passed propertyValues complying with the historyRecordStructure. + * + * @param propertyValues The values of the record. + * + * @throws IOException + */ + void addRecord(String[] propertyValues) throws IOException; + } diff --git a/src/net/java/sip/communicator/service/history/records/HistoryRecord.java b/src/net/java/sip/communicator/service/history/records/HistoryRecord.java index 398ab31d2..fa698b047 100644 --- a/src/net/java/sip/communicator/service/history/records/HistoryRecord.java +++ b/src/net/java/sip/communicator/service/history/records/HistoryRecord.java @@ -11,78 +11,89 @@ /** * @author Alexander Pelov */ -public class HistoryRecord { +public class HistoryRecord +{ - private Date timestamp; - private String[] propertyNames; - private String[] propertyValues; + private Date timestamp; + private String[] propertyNames; + private String[] propertyValues; - /** - * Constructs an entry containing multiple name-value pairs, where the names - * are taken from the defined structure. The timestamp is set to the time this - * object is created. - * - * @param entryStructure - * @param propertyValues - */ - public HistoryRecord(HistoryRecordStructure entryStructure, String[] propertyValues) { - this(entryStructure.getPropertyNames(), propertyValues, new Date()); - } + /** + * Constructs an entry containing multiple name-value pairs, where the names + * are taken from the defined structure. The timestamp is set to the time this + * object is created. + * + * @param entryStructure + * @param propertyValues + */ + public HistoryRecord(HistoryRecordStructure entryStructure, + String[] propertyValues) + { + this(entryStructure.getPropertyNames(), propertyValues, new Date()); + } - /** - * Constructs an entry containing multiple name-value pairs, where the name is not - * unique. The timestamp is set to the time this object is created. - * - * @param propertyNames - * @param propertyValues - */ - public HistoryRecord(String[] propertyNames, String[] propertyValues) { - this(propertyNames, propertyValues, new Date()); - } + /** + * Constructs an entry containing multiple name-value pairs, where the name is not + * unique. The timestamp is set to the time this object is created. + * + * @param propertyNames + * @param propertyValues + */ + public HistoryRecord(String[] propertyNames, String[] propertyValues) + { + this(propertyNames, propertyValues, new Date()); + } - /** - * Constructs an entry containing multiple name-value pairs, where the names - * are taken from the defined structure. - * - * @param entryStructure - * @param propertyValues - * @param timestamp - */ - public HistoryRecord(HistoryRecordStructure entryStructure, String[] propertyValues, Date timestamp) { - this(entryStructure.getPropertyNames(), propertyValues, timestamp); - } + /** + * Constructs an entry containing multiple name-value pairs, where the names + * are taken from the defined structure. + * + * @param entryStructure + * @param propertyValues + * @param timestamp + */ + public HistoryRecord(HistoryRecordStructure entryStructure, + String[] propertyValues, Date timestamp) + { + this(entryStructure.getPropertyNames(), propertyValues, timestamp); + } - /** - * Constructs an entry containing multiple name-value pairs, where the name is not - * unique. - * - * @param propertyNames - * @param propertyValues - * @param timestamp - */ - public HistoryRecord(String[] propertyNames, String[] propertyValues, Date timestamp) { - // TODO: Validate: Assert.assertNonNull(propertyNames, "The property names should be non-null."); - // TODO: Validate: Assert.assertNonNull(propertyValues, "The property values should be non-null."); - // TODO: Validate: Assert.assertNonNull(timestamp, "The timestamp should be non-null."); - - // TODO: Validate Assert.assertTrue(propertyNames.length == propertyValues.length, - // "The length of the property names and property values should be equal."); + /** + * Constructs an entry containing multiple name-value pairs, where the name is not + * unique. + * + * @param propertyNames + * @param propertyValues + * @param timestamp + */ + public HistoryRecord(String[] propertyNames, String[] propertyValues, + Date timestamp) + { + // TODO: Validate: Assert.assertNonNull(propertyNames, "The property names should be non-null."); + // TODO: Validate: Assert.assertNonNull(propertyValues, "The property values should be non-null."); + // TODO: Validate: Assert.assertNonNull(timestamp, "The timestamp should be non-null."); - this.propertyNames = propertyNames; - this.propertyValues = propertyValues; - this.timestamp = timestamp; - } + // TODO: Validate Assert.assertTrue(propertyNames.length == propertyValues.length, + // "The length of the property names and property values should be equal."); - public String[] getPropertyNames() { - return this.propertyNames; - } + this.propertyNames = propertyNames; + this.propertyValues = propertyValues; + this.timestamp = timestamp; + } - public String[] getPropertyValues() { - return this.propertyValues; - } + public String[] getPropertyNames() + { + return this.propertyNames; + } - public Date getTimestamp() { - return this.timestamp; - } + public String[] getPropertyValues() + { + return this.propertyValues; + } + + public Date getTimestamp() + { + return this.timestamp; + } } diff --git a/src/net/java/sip/communicator/service/history/records/HistoryRecordStructure.java b/src/net/java/sip/communicator/service/history/records/HistoryRecordStructure.java index 52b4b4965..a0fb871ad 100644 --- a/src/net/java/sip/communicator/service/history/records/HistoryRecordStructure.java +++ b/src/net/java/sip/communicator/service/history/records/HistoryRecordStructure.java @@ -9,33 +9,37 @@ /** * @author Alexander Pelov */ -public class HistoryRecordStructure { +public class HistoryRecordStructure +{ - private String[] propertyNames; + private String[] propertyNames; - /** - * Creates an entry structure object used to define the shape of the data - * stored in the history. - * - * Note that the property names are not unique, i.e. a single property - * may have 0, 1 or more values. - * - * @param propertyNames - */ - public HistoryRecordStructure(String[] propertyNames) { - // TODO: Validate: Assert.assertNonNull(propertyNames, "Parameter propertyNames should be non-null."); - - this.propertyNames = new String[propertyNames.length]; - System.arraycopy(propertyNames, 0, this.propertyNames, 0, this.propertyNames.length); - } + /** + * Creates an entry structure object used to define the shape of the data + * stored in the history. + * + * Note that the property names are not unique, i.e. a single property + * may have 0, 1 or more values. + * + * @param propertyNames + */ + public HistoryRecordStructure(String[] propertyNames) + { + // TODO: Validate: Assert.assertNonNull(propertyNames, "Parameter propertyNames should be non-null."); + + this.propertyNames = new String[propertyNames.length]; + System.arraycopy(propertyNames, 0, this.propertyNames, 0, + this.propertyNames.length); + } + + public String[] getPropertyNames() + { + return this.propertyNames; + } + + public int getPropertyCount() + { + return this.propertyNames.length; + } - - public String[] getPropertyNames() { - return this.propertyNames; - } - - public int getPropertyCount() { - return this.propertyNames.length; - } - }