-
Notifications
You must be signed in to change notification settings - Fork 38
DestinationSet should implement java.util.Set #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,3 +1,4 @@ | ||||||||
|
|
||||||||
| /* | ||||||||
| * Copyright (c) Mirth Corporation. All rights reserved. | ||||||||
| * | ||||||||
|
|
@@ -7,162 +8,221 @@ | |||||||
| * been included with this distribution in the LICENSE.txt file. | ||||||||
| */ | ||||||||
|
|
||||||||
| package com.mirth.connect.server.userutil; | ||||||||
|
|
||||||||
| import java.util.Collection; | ||||||||
| import java.util.Collections; | ||||||||
| import java.util.HashSet; | ||||||||
| import java.util.Map; | ||||||||
| import java.util.Set; | ||||||||
|
|
||||||||
| import org.mozilla.javascript.Context; | ||||||||
|
|
||||||||
| import com.mirth.connect.donkey.server.Constants; | ||||||||
| import com.mirth.connect.userutil.ImmutableConnectorMessage; | ||||||||
|
|
||||||||
| /** | ||||||||
| * Utility class used in the preprocessor or source filter/transformer to prevent the message from | ||||||||
| * being sent to specific destinations. | ||||||||
| */ | ||||||||
| public class DestinationSet { | ||||||||
|
|
||||||||
| private Map<String, Integer> destinationIdMap; | ||||||||
| private Set<Integer> metaDataIds; | ||||||||
|
|
||||||||
| /** | ||||||||
| * DestinationSet instances should NOT be constructed manually. The instance "destinationSet" | ||||||||
| * provided in the scope should be used. | ||||||||
| * | ||||||||
| * @param connectorMessage | ||||||||
| * The delegate ImmutableConnectorMessage object. | ||||||||
| */ | ||||||||
| public DestinationSet(ImmutableConnectorMessage connectorMessage) { | ||||||||
| try { | ||||||||
| if (connectorMessage.getSourceMap().containsKey(Constants.DESTINATION_SET_KEY)) { | ||||||||
| this.destinationIdMap = connectorMessage.getDestinationIdMap(); | ||||||||
| this.metaDataIds = (Set<Integer>) connectorMessage.getSourceMap().get(Constants.DESTINATION_SET_KEY); | ||||||||
| } | ||||||||
| } catch (Exception e) { | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Stop a destination from being processed for this message. | ||||||||
| * | ||||||||
| * @param metaDataIdOrConnectorName | ||||||||
| * An integer representing the metaDataId of a destination connector, or the actual | ||||||||
| * destination connector name. | ||||||||
| * @return A boolean indicating whether at least one destination connector was actually removed | ||||||||
| * from processing for this message. | ||||||||
| */ | ||||||||
| public boolean remove(Object metaDataIdOrConnectorName) { | ||||||||
| if (metaDataIds != null) { | ||||||||
| Integer metaDataId = convertToMetaDataId(metaDataIdOrConnectorName); | ||||||||
|
|
||||||||
| if (metaDataId != null) { | ||||||||
| return metaDataIds.remove(metaDataId); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| return false; | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Stop a destination from being processed for this message. | ||||||||
| * | ||||||||
| * @param metaDataIdOrConnectorNames | ||||||||
| * A collection of integers representing the metaDataId of a destination connectors, | ||||||||
| * or the actual destination connector names. JavaScript arrays can be used. | ||||||||
| * @return A boolean indicating whether at least one destination connector was actually removed | ||||||||
| * from processing for this message. | ||||||||
| */ | ||||||||
| public boolean remove(Collection<Object> metaDataIdOrConnectorNames) { | ||||||||
| boolean removed = false; | ||||||||
|
|
||||||||
| for (Object metaDataIdOrConnectorName : metaDataIdOrConnectorNames) { | ||||||||
| if (remove(metaDataIdOrConnectorName)) { | ||||||||
| removed = true; | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| return removed; | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Stop all except one destination from being processed for this message. | ||||||||
| * | ||||||||
| * @param metaDataIdOrConnectorName | ||||||||
| * An integer representing the metaDataId of a destination connector, or the actual | ||||||||
| * destination connector name. | ||||||||
| * @return A boolean indicating whether at least one destination connector was actually removed | ||||||||
| * from processing for this message. | ||||||||
| */ | ||||||||
| public boolean removeAllExcept(Object metaDataIdOrConnectorName) { | ||||||||
| if (metaDataIds != null) { | ||||||||
| Integer metaDataId = convertToMetaDataId(metaDataIdOrConnectorName); | ||||||||
|
|
||||||||
| if (metaDataId != null) { | ||||||||
| return metaDataIds.retainAll(Collections.singleton(metaDataId)); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| return false; | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Stop all except one destination from being processed for this message. | ||||||||
| * | ||||||||
| * @param metaDataIdOrConnectorNames | ||||||||
| * A collection of integers representing the metaDataId of a destination connectors, | ||||||||
| * or the actual destination connector names. JavaScript arrays can be used. | ||||||||
| * @return A boolean indicating whether at least one destination connector was actually removed | ||||||||
| * from processing for this message. | ||||||||
| */ | ||||||||
| public boolean removeAllExcept(Collection<Object> metaDataIdOrConnectorNames) { | ||||||||
| if (metaDataIds != null) { | ||||||||
| Set<Integer> set = new HashSet<Integer>(); | ||||||||
|
|
||||||||
| for (Object metaDataIdOrConnectorName : metaDataIdOrConnectorNames) { | ||||||||
| Integer metaDataId = convertToMetaDataId(metaDataIdOrConnectorName); | ||||||||
|
|
||||||||
| if (metaDataId != null) { | ||||||||
| set.add(metaDataId); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| return metaDataIds.retainAll(set); | ||||||||
| } | ||||||||
|
|
||||||||
| return false; | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Stop all destinations from being processed for this message. This does NOT mark the source | ||||||||
| * message as FILTERED. | ||||||||
| * | ||||||||
| * @return A boolean indicating whether at least one destination connector was actually removed | ||||||||
| * from processing for this message. | ||||||||
| */ | ||||||||
| public boolean removeAll() { | ||||||||
| if (metaDataIds != null && metaDataIds.size() > 0) { | ||||||||
| metaDataIds.clear(); | ||||||||
| return true; | ||||||||
| } | ||||||||
|
|
||||||||
| return false; | ||||||||
| } | ||||||||
|
|
||||||||
| private Integer convertToMetaDataId(Object metaDataIdOrConnectorName) { | ||||||||
| if (metaDataIdOrConnectorName != null) { | ||||||||
| if (metaDataIdOrConnectorName instanceof Number) { | ||||||||
| return ((Number) metaDataIdOrConnectorName).intValue(); | ||||||||
| } else if (metaDataIdOrConnectorName.getClass().getName().equals("org.mozilla.javascript.NativeNumber")) { | ||||||||
| return (Integer) Context.jsToJava(metaDataIdOrConnectorName, int.class); | ||||||||
| } else if (destinationIdMap != null) { | ||||||||
| return destinationIdMap.get(metaDataIdOrConnectorName.toString()); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| return null; | ||||||||
| } | ||||||||
| } | ||||||||
| package com.mirth.connect.server.userutil; | ||||||||
|
|
||||||||
| import java.util.Collection; | ||||||||
| import java.util.Collections; | ||||||||
| import java.util.HashSet; | ||||||||
| import java.util.Iterator; | ||||||||
| import java.util.Map; | ||||||||
| import java.util.Optional; | ||||||||
| import java.util.Set; | ||||||||
| import java.util.stream.Collectors; | ||||||||
|
|
||||||||
| import org.mozilla.javascript.Context; | ||||||||
|
|
||||||||
| import com.mirth.connect.donkey.server.Constants; | ||||||||
| import com.mirth.connect.userutil.ImmutableConnectorMessage; | ||||||||
|
|
||||||||
| /** | ||||||||
| * Utility class used in the preprocessor or source filter/transformer to prevent the message from | ||||||||
| * being sent to specific destinations. | ||||||||
| */ | ||||||||
| public class DestinationSet implements Set<Integer> { | ||||||||
|
|
||||||||
| private Map<String, Integer> destinationIdMap = Collections.emptyMap(); | ||||||||
| private Set<Integer> metaDataIds; | ||||||||
|
|
||||||||
| /** | ||||||||
| * DestinationSet instances should NOT be constructed manually. The instance "destinationSet" | ||||||||
| * provided in the scope should be used. | ||||||||
| * | ||||||||
| * @param connectorMessage | ||||||||
| * The delegate ImmutableConnectorMessage object. | ||||||||
| */ | ||||||||
| public DestinationSet(ImmutableConnectorMessage connectorMessage) { | ||||||||
| try { | ||||||||
| if (connectorMessage.getSourceMap().containsKey(Constants.DESTINATION_SET_KEY)) { | ||||||||
| this.destinationIdMap = connectorMessage.getDestinationIdMap(); | ||||||||
| this.metaDataIds = (Set<Integer>) connectorMessage.getSourceMap().get(Constants.DESTINATION_SET_KEY); | ||||||||
| } | ||||||||
| } catch (Exception e) { | ||||||||
| metaDataIds = new HashSet<>(); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Stop a destination from being processed for this message. | ||||||||
| * | ||||||||
| * @param metaDataIdOrConnectorName | ||||||||
| * An integer representing the metaDataId of a destination connector, or the actual | ||||||||
| * destination connector name. | ||||||||
| * @return A boolean indicating whether at least one destination connector was actually removed | ||||||||
| * from processing for this message. | ||||||||
| */ | ||||||||
|
||||||||
| */ | |
| */ | |
| @Override |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method DestinationSet.remove(..) could be confused with overloaded method remove, since dispatch depends on static types.
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spacing after if is inconsistent with Java conventions. Should be if (metaDataIdOrConnectorNames == null) with a space after if and before the opening brace.
This pattern appears throughout the file (lines 77, 111, 190, 201). Consistent formatting improves code readability.
| if(metaDataIdOrConnectorNames == null) { return false; } | |
| if (metaDataIdOrConnectorNames == null) { return false; } |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method DestinationSet.removeAllExcept(..) could be confused with overloaded method removeAllExcept, since dispatch depends on static types.
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spacing after if is inconsistent with Java conventions. Should be if (metaDataIdOrConnectorNames == null) with a space after if and before the opening brace.
| if(metaDataIdOrConnectorNames == null) { return false; } | |
| if (metaDataIdOrConnectorNames == null) { return false; } |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spacing after if is inconsistent with Java conventions. Should be if (metaDataIdOrConnectorNames == null) with a space after if and before the opening brace.
| if(metaDataIdOrConnectorNames == null) { return false; } | |
| if (metaDataIdOrConnectorNames == null) { return false; } |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spacing after if is inconsistent with Java conventions. Should be if (metaDataIdOrConnectorNames != null) with a space after if and before the opening brace.
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spacing after for is inconsistent with Java conventions. Should be for (Object item : metaDataIdOrConnectorNames) with a space after for.
| for(Object item : metaDataIdOrConnectorNames) { | |
| for (Object item : metaDataIdOrConnectorNames) { |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spacing after if is inconsistent with Java conventions. Should be if (m.isPresent() && metaDataIds.add(m.get())) with a space after if.
| if(m.isPresent() && metaDataIds.add(m.get())) { | |
| if (m.isPresent() && metaDataIds.add(m.get())) { |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unchecked cast from Collection<?> to Collection<Object>. While this works, it will generate a compiler warning. Consider adding @SuppressWarnings("unchecked") to this method or refactoring to avoid the cast.
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unchecked cast from Collection<?> to Collection<Object>. While this works, it will generate a compiler warning. Consider adding @SuppressWarnings("unchecked") to this method or refactoring to avoid the cast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The constructor leaves
metaDataIdsnull when the source map does not containDESTINATION_SET_KEY. This will cause NullPointerException in all Set interface methods (size(), isEmpty(), iterator(), etc.) when the key is not present.The catch block on line 50 only executes if an exception is thrown, not when the if-condition on line 45 is false. You need to initialize
metaDataIdsto an empty HashSet in all cases where it would otherwise remain null.Suggested fix: