package org.dcm4che3.net; import org.dcm4che3.conf.core.api.ConfigurableClass; import org.dcm4che3.conf.core.api.ConfigurableProperty; import org.dcm4che3.data.UID; import java.io.Serializable; import java.util.*; import static org.dcm4che3.net.TransferCapability.Role.SCU; /** * Alternative representation of Transfer Capabilities for an application entity * * @author Roman K */ @ConfigurableClass public class TCGroupConfigAEExtension extends AEExtension { /** * Certain components' logic may be bound to these group names */ public enum DefaultGroup { STORAGE, PPS, QUERY, RETRIEVE, MWL, STORAGE_COMMITMENT } @ConfigurableProperty( label = "Enabled transfer capability groups - SCU" ) Map<String, TCGroupDetails> scuTCs = new TreeMap<String, TCGroupDetails>(); @ConfigurableProperty( label = "Enabled transfer capability groups - SCP" ) Map<String, TCGroupDetails> scpTCs = new TreeMap<String, TCGroupDetails>(); public TCGroupConfigAEExtension() { } public TCGroupConfigAEExtension(EnumSet<DefaultGroup> scpGroups, EnumSet<DefaultGroup> scuGroups) { for (DefaultGroup defaultGroup : scpGroups) scpTCs.put(defaultGroup.name(), new TCGroupDetails()); for (DefaultGroup defaultGroup : scuGroups) scuTCs.put(defaultGroup.name(), new TCGroupDetails()); } /** * Shortcut to define which default SCP groups are supported, omitting exclusion details * * @return */ public EnumSet<DefaultGroup> getSupportedDefaultScpGroups() { EnumSet<DefaultGroup> groups = EnumSet.noneOf(DefaultGroup.class); for (Map.Entry<String, TCGroupDetails> entry : scpTCs.entrySet()) { try { DefaultGroup group = DefaultGroup.valueOf(entry.getKey()); groups.add(group); } catch (IllegalArgumentException e) { //noop } } return groups; } /** * Restricts transfer syntaxes for all SOP classes for this AE to Little Endian Implicit and Video-related ones */ public void setLEIAndVideoOnly(boolean leiAndVideoOnly) { if (leiAndVideoOnly) { for (TCGroupDetails tcGroupDetails : scpTCs.values()) whitelistLEIAndVideoTSs(tcGroupDetails); for (TCGroupDetails tcGroupDetails : scuTCs.values()) whitelistLEIAndVideoTSs(tcGroupDetails); } else { for (TCGroupDetails tcGroupDetails : scpTCs.values()) tcGroupDetails.getWhitelistedTransferSyntaxes().clear(); for (TCGroupDetails tcGroupDetails : scuTCs.values()) tcGroupDetails.getWhitelistedTransferSyntaxes().clear(); } } private void whitelistLEIAndVideoTSs(TCGroupDetails tcGroupDetails) { tcGroupDetails.getWhitelistedTransferSyntaxes().clear(); tcGroupDetails.getWhitelistedTransferSyntaxes().add(UID.ImplicitVRLittleEndian); for (String videoTsuid : DefaultTransferCapabilities.VIDEO_TSUIDS) { tcGroupDetails.getWhitelistedTransferSyntaxes().add(videoTsuid); } } public Map<String, TCGroupDetails> getScuTCs() { return scuTCs; } public void setScuTCs(Map<String, TCGroupDetails> scuTCs) { this.scuTCs = scuTCs; } public Map<String, TCGroupDetails> getScpTCs() { return scpTCs; } public void setScpTCs(Map<String, TCGroupDetails> scpTCs) { this.scpTCs = scpTCs; } @ConfigurableClass public static class TCGroupDetails implements Serializable { public TCGroupDetails() { } @ConfigurableProperty private List<String> excludedTransferSyntaxes = new ArrayList<String>(); @ConfigurableProperty( description = "If not empty, all the syntaxes but those specified by this parameter" + "will be effectively removed from this AE's transfer capabilities") private List<String> whitelistedTransferSyntaxes = new ArrayList<String>(); @ConfigurableProperty( label = "Excluded SOP classes", description = "This AE will include all transfer capabilities from the corresponding group, " + "except those with SOP classes specified here" ) private List<String> excludedTransferCapabilities = new ArrayList<String>(); public List<String> getExcludedTransferSyntaxes() { return excludedTransferSyntaxes; } public void setExcludedTransferSyntaxes(List<String> excludedTransferSyntaxes) { this.excludedTransferSyntaxes = excludedTransferSyntaxes; } public List<String> getExcludedTransferCapabilities() { return excludedTransferCapabilities; } public void setExcludedTransferCapabilities(List<String> excludedTransferCapabilities) { this.excludedTransferCapabilities = excludedTransferCapabilities; } public List<String> getWhitelistedTransferSyntaxes() { return whitelistedTransferSyntaxes; } public void setWhitelistedTransferSyntaxes(List<String> whitelistedTransferSyntaxes) { this.whitelistedTransferSyntaxes = whitelistedTransferSyntaxes; } } @Override public void reconfigure(AEExtension from) { TCGroupConfigAEExtension tcGroupConfigAEExtension = (TCGroupConfigAEExtension) from; setScpTCs(tcGroupConfigAEExtension.getScpTCs()); setScuTCs(tcGroupConfigAEExtension.getScuTCs()); } public static List<TransferCapability> getTCsForDefaultGroup(DefaultGroup group) { ArrayList<TransferCapability> transferCapabilities; switch (group) { case STORAGE: transferCapabilities = new ArrayList<TransferCapability>(); allTCToList(transferCapabilities, DefaultTransferCapabilities.IMAGE_CUIDS, null, DefaultTransferCapabilities.IMAGE_TSUIDS); allTCToList(transferCapabilities, DefaultTransferCapabilities.VIDEO_CUIDS, null, DefaultTransferCapabilities.VIDEO_TSUIDS); allTCToList(transferCapabilities, DefaultTransferCapabilities.OTHER_CUIDS, null, DefaultTransferCapabilities.OTHER_TSUIDS); allTCToList(transferCapabilities, new String[]{UID.InstanceAvailabilityNotificationSOPClass, UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian); return transferCapabilities; case QUERY: transferCapabilities = new ArrayList<TransferCapability>(); allTCToList(transferCapabilities, DefaultTransferCapabilities.QUERY_CUIDS, EnumSet.allOf(QueryOption.class), DefaultTransferCapabilities.OTHER_TSUIDS); allTCToList(transferCapabilities, new String[]{UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian); return transferCapabilities; case RETRIEVE: transferCapabilities = new ArrayList<TransferCapability>(); allTCToList(transferCapabilities, DefaultTransferCapabilities.RETRIEVE_CUIDS, EnumSet.of(QueryOption.RELATIONAL), DefaultTransferCapabilities.OTHER_TSUIDS); allTCToList(transferCapabilities, new String[]{UID.CompositeInstanceRetrieveWithoutBulkDataGET, UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian); return transferCapabilities; case MWL: transferCapabilities = new ArrayList<TransferCapability>(); allTCToList(transferCapabilities, new String[]{UID.ModalityWorklistInformationModelFIND, UID.VerificationSOPClass}, EnumSet.allOf(QueryOption.class), UID.ImplicitVRLittleEndian); return transferCapabilities; case PPS: transferCapabilities = new ArrayList<TransferCapability>(); allTCToList(transferCapabilities, new String[]{UID.ModalityPerformedProcedureStepSOPClass, UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian); return transferCapabilities; case STORAGE_COMMITMENT: transferCapabilities = new ArrayList<TransferCapability>(); allTCToList(transferCapabilities, new String[]{UID.StorageCommitmentPushModelSOPClass, UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian); return transferCapabilities; default: throw new RuntimeException("Group " + group + " is undefined"); } } private static void allTCToList(ArrayList<TransferCapability> transferCapabilities, String[] imageCuids, EnumSet<QueryOption> queryOptions, String... transferSyntaxes) { for (String cuid : imageCuids) { String name = UID.nameOf(cuid).replace('/', ' '); TransferCapability tc = new TransferCapability(name, cuid, SCU, transferSyntaxes); tc.setQueryOptions(queryOptions); transferCapabilities.add(tc); } } }