test_class.declarator: client
test_class.modifier: @Mock
  	@Bind
  	private
test_class.original_string: @Mock
  	@Bind
  	private Client client;
test_class.type: Client
test_class.var_name: client
test_class.declarator: config
test_class.modifier: @Mock
  	@Bind
  	private
test_class.original_string: @Mock
  	@Bind
  	private ChatNotificationsConfig config;
test_class.type: ChatNotificationsConfig
test_class.var_name: config
test_class.declarator: chatMessageManager
test_class.modifier: @Mock
  	@Bind
  	private
test_class.original_string: @Mock
  	@Bind
  	private ChatMessageManager chatMessageManager;
test_class.type: ChatMessageManager
test_class.var_name: chatMessageManager
test_class.declarator: notifier
test_class.modifier: @Mock
  	@Bind
  	private
test_class.original_string: @Mock
  	@Bind
  	private Notifier notifier;
test_class.type: Notifier
test_class.var_name: notifier
test_class.declarator: chatNotificationsPlugin
test_class.modifier: @Inject
  	private
test_class.original_string: @Inject
  	private ChatNotificationsPlugin chatNotificationsPlugin;
test_class.type: ChatNotificationsPlugin
test_class.var_name: chatNotificationsPlugin
test_class.file: runelite-client/src/test/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPluginTest.java
test_class.identifier: ChatNotificationsPluginTest
test_case.body: @Test
  	public void testHighlightOwnNameNbsp()
  	{
  		Player player = mock(Player.class);
  		when(player.getName()).thenReturn("Logic Knot");
  		when(client.getLocalPlayer()).thenReturn(player);
  
  		when(config.highlightOwnName()).thenReturn(true);
  
  		MessageNode messageNode = mock(MessageNode.class);
  		when(messageNode.getValue()).thenReturn("<col=005f00>Logic\u00a0Knot received a drop: Adamant longsword</col>");
  		ChatMessage chatMessage = new ChatMessage(messageNode, ChatMessageType.GAMEMESSAGE, "", "", "", 0);
  		chatNotificationsPlugin.onChatMessage(chatMessage);
  
  		// set value uses our player name, which has nbsp replaced
  		verify(messageNode).setValue("<col=005f00><colHIGHLIGHT><u>Logic Knot</u><colNORMAL> received a drop: Adamant longsword</col>");
  	}
test_case.class_method_signature: ChatNotificationsPluginTest.testHighlightOwnNameNbsp()
test_case.full_signature: @Test public void testHighlightOwnNameNbsp()
test_case.identifier: testHighlightOwnNameNbsp
test_case.invocations: mock thenReturn when getName thenReturn when getLocalPlayer thenReturn when highlightOwnName mock thenReturn when getValue onChatMessage setValue verify
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void testHighlightOwnNameNbsp()
focal_class.declarator: client
focal_class.modifier: @Inject
  	private
focal_class.original_string: @Inject
  	private Client client;
focal_class.type: Client
focal_class.var_name: client
focal_class.declarator: config
focal_class.modifier: @Inject
  	private
focal_class.original_string: @Inject
  	private ChatNotificationsConfig config;
focal_class.type: ChatNotificationsConfig
focal_class.var_name: config
focal_class.declarator: chatMessageManager
focal_class.modifier: @Inject
  	private
focal_class.original_string: @Inject
  	private ChatMessageManager chatMessageManager;
focal_class.type: ChatMessageManager
focal_class.var_name: chatMessageManager
focal_class.declarator: notifier
focal_class.modifier: @Inject
  	private
focal_class.original_string: @Inject
  	private Notifier notifier;
focal_class.type: Notifier
focal_class.var_name: notifier
focal_class.declarator: usernameMatcher = null
focal_class.modifier: private
focal_class.original_string: private Pattern usernameMatcher = null;
focal_class.type: Pattern
focal_class.var_name: usernameMatcher
focal_class.declarator: usernameReplacer = ""
focal_class.modifier: private
focal_class.original_string: private String usernameReplacer = "";
focal_class.type: String
focal_class.var_name: usernameReplacer
focal_class.declarator: highlightMatcher = null
focal_class.modifier: private
focal_class.original_string: private Pattern highlightMatcher = null;
focal_class.type: Pattern
focal_class.var_name: highlightMatcher
focal_class.file: runelite-client/src/main/java/net/runelite/client/plugins/chatnotifications/ChatNotificationsPlugin.java
focal_class.identifier: ChatNotificationsPlugin
focal_class.class_method_signature: ChatNotificationsPlugin.provideConfig(ConfigManager configManager)
focal_class.full_signature: @Provides ChatNotificationsConfig provideConfig(ConfigManager configManager)
focal_class.identifier: provideConfig
focal_class.modifiers: @Provides
focal_class.parameters: (ConfigManager configManager)
focal_class.return: ChatNotificationsConfig
focal_class.signature: ChatNotificationsConfig provideConfig(ConfigManager configManager)
focal_class.class_method_signature: ChatNotificationsPlugin.startUp()
focal_class.full_signature: @Override public void startUp()
focal_class.identifier: startUp
focal_class.modifiers: @Override public
focal_class.parameters: ()
focal_class.return: void
focal_class.signature: void startUp()
focal_class.class_method_signature: ChatNotificationsPlugin.onGameStateChanged(GameStateChanged event)
focal_class.full_signature: @Subscribe public void onGameStateChanged(GameStateChanged event)
focal_class.identifier: onGameStateChanged
focal_class.modifiers: @Subscribe public
focal_class.parameters: (GameStateChanged event)
focal_class.return: void
focal_class.signature: void onGameStateChanged(GameStateChanged event)
focal_class.class_method_signature: ChatNotificationsPlugin.onConfigChanged(ConfigChanged event)
focal_class.full_signature: @Subscribe public void onConfigChanged(ConfigChanged event)
focal_class.identifier: onConfigChanged
focal_class.modifiers: @Subscribe public
focal_class.parameters: (ConfigChanged event)
focal_class.return: void
focal_class.signature: void onConfigChanged(ConfigChanged event)
focal_class.class_method_signature: ChatNotificationsPlugin.updateHighlights()
focal_class.full_signature: private void updateHighlights()
focal_class.identifier: updateHighlights
focal_class.modifiers: private
focal_class.parameters: ()
focal_class.return: void
focal_class.signature: void updateHighlights()
focal_class.class_method_signature: ChatNotificationsPlugin.onChatMessage(ChatMessage chatMessage)
focal_class.full_signature: @Subscribe public void onChatMessage(ChatMessage chatMessage)
focal_class.identifier: onChatMessage
focal_class.modifiers: @Subscribe public
focal_class.parameters: (ChatMessage chatMessage)
focal_class.return: void
focal_class.signature: void onChatMessage(ChatMessage chatMessage)
focal_class.class_method_signature: ChatNotificationsPlugin.sendNotification(ChatMessage message)
focal_class.full_signature: private void sendNotification(ChatMessage message)
focal_class.identifier: sendNotification
focal_class.modifiers: private
focal_class.parameters: (ChatMessage message)
focal_class.return: void
focal_class.signature: void sendNotification(ChatMessage message)
focal_class.class_method_signature: ChatNotificationsPlugin.quoteAndIgnoreColor(String str)
focal_class.full_signature: private String quoteAndIgnoreColor(String str)
focal_class.identifier: quoteAndIgnoreColor
focal_class.modifiers: private
focal_class.parameters: (String str)
focal_class.return: String
focal_class.signature: String quoteAndIgnoreColor(String str)
focal_class.class_method_signature: ChatNotificationsPlugin.getLastColor(String str)
focal_class.full_signature: private static String getLastColor(String str)
focal_class.identifier: getLastColor
focal_class.modifiers: private static
focal_class.parameters: (String str)
focal_class.return: String
focal_class.signature: String getLastColor(String str)
focal_class.class_method_signature: ChatNotificationsPlugin.stripColor(String str)
focal_class.full_signature: @VisibleForTesting static String stripColor(String str)
focal_class.identifier: stripColor
focal_class.modifiers: @VisibleForTesting static
focal_class.parameters: (String str)
focal_class.return: String
focal_class.signature: String stripColor(String str)
focal_class.superclass: extends Plugin
focal_method.body: @Subscribe
  	public void onChatMessage(ChatMessage chatMessage)
  	{
  		MessageNode messageNode = chatMessage.getMessageNode();
  		boolean update = false;
  
  		switch (chatMessage.getType())
  		{
  			case TRADEREQ:
  				if (chatMessage.getMessage().contains("wishes to trade with you.") && config.notifyOnTrade())
  				{
  					notifier.notify(chatMessage.getMessage());
  				}
  				break;
  			case CHALREQ_TRADE:
  				if (chatMessage.getMessage().contains("wishes to duel with you.") && config.notifyOnDuel())
  				{
  					notifier.notify(chatMessage.getMessage());
  				}
  				break;
  			case BROADCAST:
  				if (config.notifyOnBroadcast())
  				{
  					// Some broadcasts have links attached, notated by `|` followed by a number, while others contain color tags.
  					// We don't want to see either in the printed notification.
  					String broadcast = chatMessage.getMessage();
  
  					int urlTokenIndex = broadcast.lastIndexOf('|');
  					if (urlTokenIndex != -1)
  					{
  						broadcast = broadcast.substring(0, urlTokenIndex);
  					}
  
  					notifier.notify(Text.removeFormattingTags(broadcast));
  				}
  				break;
  			case CONSOLE:
  				// Don't notify for notification messages
  				if (chatMessage.getName().equals(RuneLiteProperties.getTitle()))
  				{
  					return;
  				}
  				break;
  		}
  
  		if (usernameMatcher == null && client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null)
  		{
  			String username = client.getLocalPlayer().getName();
  			String pattern = Arrays.stream(username.split(" "))
  				.map(s -> s.isEmpty() ? "" : Pattern.quote(s))
  				.collect(Collectors.joining("[\u00a0\u0020]")); // space or nbsp
  			usernameMatcher = Pattern.compile("\\b" + pattern + "\\b", Pattern.CASE_INSENSITIVE);
  			usernameReplacer = "<col" + ChatColorType.HIGHLIGHT.name() + "><u>" + username + "</u><col" + ChatColorType.NORMAL.name() + ">";
  		}
  
  		if (config.highlightOwnName() && usernameMatcher != null)
  		{
  			Matcher matcher = usernameMatcher.matcher(messageNode.getValue());
  			if (matcher.find())
  			{
  				messageNode.setValue(matcher.replaceAll(usernameReplacer));
  				update = true;
  				if (config.notifyOnOwnName() && (chatMessage.getType() == ChatMessageType.PUBLICCHAT
  					|| chatMessage.getType() == ChatMessageType.PRIVATECHAT
  					|| chatMessage.getType() == ChatMessageType.FRIENDSCHAT
  					|| chatMessage.getType() == ChatMessageType.MODCHAT
  					|| chatMessage.getType() == ChatMessageType.MODPRIVATECHAT))
  				{
  					sendNotification(chatMessage);
  				}
  			}
  		}
  
  		if (highlightMatcher != null)
  		{
  			String nodeValue = messageNode.getValue();
  			Matcher matcher = highlightMatcher.matcher(nodeValue);
  			boolean found = false;
  			StringBuffer stringBuffer = new StringBuffer();
  
  			while (matcher.find())
  			{
  				String value = matcher.group();
  
  				// Determine the ending color by:
  				// 1) use the color from value if it has one
  				// 2) use the last color from stringBuffer + <content between last match and current match>
  				// To do #2 we just search for the last col tag after calling appendReplacement
  				String endColor = getLastColor(value);
  
  				// Strip color tags from the highlighted region so that it remains highlighted correctly
  				value = stripColor(value);
  
  				matcher.appendReplacement(stringBuffer, "<col" + ChatColorType.HIGHLIGHT + '>' + value);
  
  				if (endColor == null)
  				{
  					endColor = getLastColor(stringBuffer.toString());
  				}
  
  				// Append end color
  				stringBuffer.append(endColor == null ? "<col" + ChatColorType.NORMAL + ">" : endColor);
  
  				update = true;
  				found = true;
  			}
  
  			if (found)
  			{
  				matcher.appendTail(stringBuffer);
  				messageNode.setValue(stringBuffer.toString());
  
  				if (config.notifyOnHighlight())
  				{
  					sendNotification(chatMessage);
  				}
  			}
  		}
  
  		if (update)
  		{
  			messageNode.setRuneLiteFormatMessage(messageNode.getValue());
  			chatMessageManager.update(messageNode);
  		}
  	}
focal_method.class_method_signature: ChatNotificationsPlugin.onChatMessage(ChatMessage chatMessage)
focal_method.full_signature: @Subscribe public void onChatMessage(ChatMessage chatMessage)
focal_method.identifier: onChatMessage
focal_method.invocations: getMessageNode getType contains getMessage notifyOnTrade notify getMessage contains getMessage notifyOnDuel notify getMessage notifyOnBroadcast getMessage lastIndexOf substring notify removeFormattingTags equals getName getTitle getLocalPlayer getName getLocalPlayer getName getLocalPlayer collect map stream split isEmpty quote joining compile name name highlightOwnName matcher getValue find setValue replaceAll notifyOnOwnName getType getType getType getType getType sendNotification getValue matcher find group getLastColor stripColor appendReplacement getLastColor toString append appendTail setValue toString notifyOnHighlight sendNotification setRuneLiteFormatMessage getValue update
focal_method.modifiers: @Subscribe public
focal_method.parameters: (ChatMessage chatMessage)
focal_method.return: void
focal_method.signature: void onChatMessage(ChatMessage chatMessage)