cache some information generated from body like isEmojiOnly, fileParams and isGeoUri

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Message.java             | 198 
src/main/java/eu/siacs/conversations/services/NotificationService.java |   2 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java      |   8 
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java    |   2 
src/main/java/eu/siacs/conversations/utils/GeoHelper.java              |   4 
src/main/java/eu/siacs/conversations/utils/UIHelper.java               |   2 
6 files changed, 98 insertions(+), 118 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Message.java 🔗

@@ -90,6 +90,11 @@ public class Message extends AbstractEntity {
 	private String axolotlFingerprint = null;
 	private String errorMessage = null;
 
+	private Boolean isGeoUri = null;
+	private Boolean isEmojisOnly = null;
+	private Boolean treatAsDownloadable = null;
+	private FileParams fileParams = null;
+
 	private Message(Conversation conversation) {
 		this.conversation = conversation;
 	}
@@ -195,21 +200,21 @@ public class Message extends AbstractEntity {
 	public static Message createStatusMessage(Conversation conversation, String body) {
 		final Message message = new Message(conversation);
 		message.setType(Message.TYPE_STATUS);
-		message.setBody(body);
+		message.body = body;
 		return message;
 	}
 
 	public static Message createLoadMoreMessage(Conversation conversation) {
 		final Message message = new Message(conversation);
 		message.setType(Message.TYPE_STATUS);
-		message.setBody("LOAD_MORE");
+		message.body = "LOAD_MORE";
 		return message;
 	}
 
 	public static Message createDateSeparator(Message message) {
 		final Message separator = new Message(message.getConversation());
 		separator.setType(Message.TYPE_STATUS);
-		separator.setBody(MessageAdapter.DATE_SEPARATOR_BODY);
+		separator.body = MessageAdapter.DATE_SEPARATOR_BODY;
 		separator.setTime(message.getTimeSent());
 		return separator;
 	}
@@ -279,11 +284,15 @@ public class Message extends AbstractEntity {
 		return body;
 	}
 
-	public void setBody(String body) {
+	public synchronized void setBody(String body) {
 		if (body == null) {
 			throw new Error("You should not set the message body to null");
 		}
 		this.body = body;
+		this.isGeoUri = null;
+		this.isEmojisOnly = null;
+		this.treatAsDownloadable = null;
+		this.fileParams = null;
 	}
 
 	public String getErrorMessage() {
@@ -401,7 +410,8 @@ public class Message extends AbstractEntity {
 		return this.transferable;
 	}
 
-	public void setTransferable(Transferable transferable) {
+	public synchronized void setTransferable(Transferable transferable) {
+		this.fileParams = null;
 		this.transferable = transferable;
 	}
 
@@ -496,8 +506,8 @@ public class Message extends AbstractEntity {
 						this.edited() == message.edited() &&
 						(message.getTimeSent() - this.getTimeSent()) <= (Config.MESSAGE_MERGE_WINDOW * 1000) &&
 						this.getBody().length() + message.getBody().length() <= Config.MAX_DISPLAY_MESSAGE_CHARS &&
-						!GeoHelper.isGeoUri(message.getBody()) &&
-						!GeoHelper.isGeoUri(this.body) &&
+						!message.isGeoUri()&&
+						!this.isGeoUri() &&
 						!message.treatAsDownloadable() &&
 						!this.treatAsDownloadable() &&
 						!message.getBody().startsWith(ME_COMMAND) &&
@@ -651,120 +661,92 @@ public class Message extends AbstractEntity {
 		}
 	}
 
-	public boolean treatAsDownloadable() {
-		if (body.trim().contains(" ")) {
-			return false;
-		}
-		try {
-			final URL url = new URL(body);
-			final String ref = url.getRef();
-			final String protocol = url.getProtocol();
-			final boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}");
-			return (AesGcmURLStreamHandler.PROTOCOL_NAME.equalsIgnoreCase(protocol) && encrypted)
-					|| (("http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol)) && (oob || encrypted));
+	public synchronized boolean treatAsDownloadable() {
+		if (treatAsDownloadable == null) {
+			if (body.trim().contains(" ")) {
+				treatAsDownloadable = false;
+			}
+			try {
+				final URL url = new URL(body);
+				final String ref = url.getRef();
+				final String protocol = url.getProtocol();
+				final boolean encrypted = ref != null && ref.matches("([A-Fa-f0-9]{2}){48}");
+				treatAsDownloadable = (AesGcmURLStreamHandler.PROTOCOL_NAME.equalsIgnoreCase(protocol) && encrypted)
+						|| (("http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol)) && (oob || encrypted));
 
-		} catch (MalformedURLException e) {
-			return false;
+			} catch (MalformedURLException e) {
+				treatAsDownloadable = false;
+			}
 		}
+		return treatAsDownloadable;
 	}
 
-	public boolean bodyIsOnlyEmojis() {
-		return EmojiManager.isOnlyEmojis(body.replaceAll("\\s",""));
+	public synchronized boolean bodyIsOnlyEmojis() {
+		if (isEmojisOnly == null) {
+			isEmojisOnly = EmojiManager.isOnlyEmojis(body.replaceAll("\\s", ""));
+		}
+		return isEmojisOnly;
 	}
 
-	public FileParams getFileParams() {
-		FileParams params = getLegacyFileParams();
-		if (params != null) {
-			return params;
-		}
-		params = new FileParams();
-		if (this.transferable != null) {
-			params.size = this.transferable.getFileSize();
+	public synchronized boolean isGeoUri() {
+		if (isGeoUri == null) {
+			isGeoUri = GeoHelper.GEO_URI.matcher(body).matches();
 		}
-		if (body == null) {
-			return params;
-		}
-		String parts[] = body.split("\\|");
-		switch (parts.length) {
-			case 1:
-				try {
-					params.size = Long.parseLong(parts[0]);
-				} catch (NumberFormatException e) {
+		return isGeoUri;
+	}
+
+	public synchronized FileParams getFileParams() {
+		if (fileParams == null) {
+			fileParams = new FileParams();
+			if (this.transferable != null) {
+				fileParams.size = this.transferable.getFileSize();
+			}
+			String parts[] = body == null ? new String[0] : body.split("\\|");
+			switch (parts.length) {
+				case 1:
 					try {
-						params.url = new URL(parts[0]);
-					} catch (MalformedURLException e1) {
-						params.url = null;
+						fileParams.size = Long.parseLong(parts[0]);
+					} catch (NumberFormatException e) {
+						fileParams.url = parseUrl(parts[0]);
 					}
-				}
-				break;
-			case 2:
-			case 4:
-				try {
-					params.url = new URL(parts[0]);
-				} catch (MalformedURLException e1) {
-					params.url = null;
-				}
-				try {
-					params.size = Long.parseLong(parts[1]);
-				} catch (NumberFormatException e) {
-					params.size = 0;
-				}
-				try {
-					params.width = Integer.parseInt(parts[2]);
-				} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
-					params.width = 0;
-				}
-				try {
-					params.height = Integer.parseInt(parts[3]);
-				} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
-					params.height = 0;
-				}
-				break;
-			case 3:
-				try {
-					params.size = Long.parseLong(parts[0]);
-				} catch (NumberFormatException e) {
-					params.size = 0;
-				}
-				try {
-					params.width = Integer.parseInt(parts[1]);
-				} catch (NumberFormatException e) {
-					params.width = 0;
-				}
-				try {
-					params.height = Integer.parseInt(parts[2]);
-				} catch (NumberFormatException e) {
-					params.height = 0;
-				}
-				break;
+					break;
+				case 4:
+					fileParams.width = parseInt(parts[2]);
+					fileParams.height = parseInt(parts[3]);
+				case 2:
+					fileParams.url = parseUrl(parts[0]);
+					fileParams.size = parseLong(parts[1]);
+					break;
+				case 3:
+					fileParams.size = parseLong(parts[0]);
+					fileParams.width = parseInt(parts[1]);
+					fileParams.height = parseInt(parts[2]);
+					break;
+			}
 		}
-		return params;
+		return fileParams;
 	}
 
-	public FileParams getLegacyFileParams() {
-		FileParams params = new FileParams();
-		if (body == null) {
-			return params;
+	private static long parseLong(String value) {
+		try {
+			return Long.parseLong(value);
+		} catch (NumberFormatException e) {
+			return 0;
 		}
-		String parts[] = body.split(",");
-		if (parts.length == 3) {
-			try {
-				params.size = Long.parseLong(parts[0]);
-			} catch (NumberFormatException e) {
-				return null;
-			}
-			try {
-				params.width = Integer.parseInt(parts[1]);
-			} catch (NumberFormatException e) {
-				return null;
-			}
-			try {
-				params.height = Integer.parseInt(parts[2]);
-			} catch (NumberFormatException e) {
-				return null;
-			}
-			return params;
-		} else {
+	}
+
+	private static int parseInt(String value) {
+		try {
+			return Integer.parseInt(value);
+		} catch (NumberFormatException e) {
+			return 0;
+		}
+	}
+
+	private static URL parseUrl(String value) {
+		try {
+			return new URL(value);
+		} catch (MalformedURLException e) {
 			return null;
 		}
 	}

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -618,7 +618,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 			MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission);
 			MenuItem deleteFile = menu.findItem(R.id.delete_file);
 			MenuItem showErrorMessage = menu.findItem(R.id.show_error_message);
-			if (!treatAsFile && !GeoHelper.isGeoUri(m.getBody()) && !m.treatAsDownloadable()) {
+			if (!treatAsFile && !m.isGeoUri() && !m.treatAsDownloadable()) {
 				selectText.setVisible(ListSelectionManager.isSupported());
 			}
 			if (m.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
@@ -636,7 +636,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 				sendAgain.setVisible(true);
 			}
 			if (m.hasFileOnRemoteHost()
-					|| GeoHelper.isGeoUri(m.getBody())
+					|| m.isGeoUri()
 					|| m.treatAsDownloadable()
 					|| (t != null && t instanceof HttpDownloadConnection)) {
 				copyUrl.setVisible(true);
@@ -713,7 +713,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 	private void shareWith(Message message) {
 		Intent shareIntent = new Intent();
 		shareIntent.setAction(Intent.ACTION_SEND);
-		if (GeoHelper.isGeoUri(message.getBody())) {
+		if (message.isGeoUri()) {
 			shareIntent.putExtra(Intent.EXTRA_TEXT, message.getBody());
 			shareIntent.setType("text/plain");
 		} else if (!message.isFileOrImage()) {
@@ -785,7 +785,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 	private void copyUrl(Message message) {
 		final String url;
 		final int resId;
-		if (GeoHelper.isGeoUri(message.getBody())) {
+		if (message.isGeoUri()) {
 			resId = R.string.location;
 			url = message.getBody();
 		} else if (message.hasFileOnRemoteHost()) {

src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java 🔗

@@ -790,7 +790,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
 		} else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
 			displayDecryptionFailed(viewHolder,darkBackground);
 		} else {
-			if (GeoHelper.isGeoUri(message.getBody())) {
+			if (message.isGeoUri()) {
 				displayLocationMessage(viewHolder,message);
 			} else if (message.bodyIsOnlyEmojis()) {
 				displayEmojiMessage(viewHolder, message.getBody().replaceAll("\\s",""));

src/main/java/eu/siacs/conversations/utils/GeoHelper.java 🔗

@@ -16,9 +16,7 @@ import eu.siacs.conversations.entities.Message;
 public class GeoHelper {
 	public static Pattern GEO_URI = Pattern.compile("geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?", Pattern.CASE_INSENSITIVE);
 
-	public static boolean isGeoUri(String body) {
-		return body != null && GEO_URI.matcher(body).matches();
-	}
+
 
 	public static ArrayList<Intent> createGeoIntentsFromMessage(Message message) {
 		final ArrayList<Intent> intents = new ArrayList<>();

src/main/java/eu/siacs/conversations/utils/UIHelper.java 🔗

@@ -202,7 +202,7 @@ public class UIHelper {
 			if (body.startsWith(Message.ME_COMMAND)) {
 				return new Pair<>(body.replaceAll("^" + Message.ME_COMMAND,
 						UIHelper.getMessageDisplayName(message) + " "), false);
-			} else if (GeoHelper.isGeoUri(message.getBody())) {
+			} else if (message.isGeoUri()) {
 				if (message.getStatus() == Message.STATUS_RECEIVED) {
 					return new Pair<>(context.getString(R.string.received_location), true);
 				} else {