001package org.dcm4che3.net;
002
003import org.dcm4che3.conf.core.api.ConfigurableClass;
004import org.dcm4che3.conf.core.api.ConfigurableProperty;
005import org.dcm4che3.data.UID;
006
007import java.io.Serializable;
008import java.util.*;
009
010import static org.dcm4che3.net.TransferCapability.Role.SCU;
011
012/**
013 * Alternative representation of Transfer Capabilities for an application entity
014 *
015 * @author Roman K
016 */
017@ConfigurableClass
018public class TCGroupConfigAEExtension extends AEExtension {
019
020    /**
021     * Certain components' logic may be bound to these group names
022     */
023    public enum DefaultGroup {
024        STORAGE,
025        PPS,
026        QUERY,
027        RETRIEVE,
028        MWL,
029        STORAGE_COMMITMENT
030    }
031
032    @ConfigurableProperty(
033            label = "Enabled transfer capability groups - SCU"
034    )
035    Map<String, TCGroupDetails> scuTCs = new TreeMap<String, TCGroupDetails>();
036
037
038    @ConfigurableProperty(
039            label = "Enabled transfer capability groups - SCP"
040    )
041    Map<String, TCGroupDetails> scpTCs = new TreeMap<String, TCGroupDetails>();
042
043    public TCGroupConfigAEExtension() {
044    }
045
046    public TCGroupConfigAEExtension(EnumSet<DefaultGroup> scpGroups, EnumSet<DefaultGroup> scuGroups) {
047        for (DefaultGroup defaultGroup : scpGroups) scpTCs.put(defaultGroup.name(), new TCGroupDetails());
048        for (DefaultGroup defaultGroup : scuGroups) scuTCs.put(defaultGroup.name(), new TCGroupDetails());
049    }
050
051    /**
052     * Shortcut to define which default SCP groups are supported, omitting exclusion details
053     *
054     * @return
055     */
056    public EnumSet<DefaultGroup> getSupportedDefaultScpGroups() {
057        EnumSet<DefaultGroup> groups = EnumSet.noneOf(DefaultGroup.class);
058        for (Map.Entry<String, TCGroupDetails> entry : scpTCs.entrySet()) {
059
060            try {
061                DefaultGroup group = DefaultGroup.valueOf(entry.getKey());
062                groups.add(group);
063            } catch (IllegalArgumentException e) {
064                //noop
065            }
066        }
067        return groups;
068    }
069
070    /**
071     * Restricts transfer syntaxes for all SOP classes for this AE to Little Endian Implicit and Video-related ones
072     */
073    public void setLEIAndVideoOnly(boolean leiAndVideoOnly) {
074        if (leiAndVideoOnly) {
075            for (TCGroupDetails tcGroupDetails : scpTCs.values())
076                whitelistLEIAndVideoTSs(tcGroupDetails);
077            for (TCGroupDetails tcGroupDetails : scuTCs.values())
078                whitelistLEIAndVideoTSs(tcGroupDetails);
079        } else {
080
081            for (TCGroupDetails tcGroupDetails : scpTCs.values())
082                tcGroupDetails.getWhitelistedTransferSyntaxes().clear();
083            for (TCGroupDetails tcGroupDetails : scuTCs.values())
084                tcGroupDetails.getWhitelistedTransferSyntaxes().clear();
085        }
086    }
087
088    private void whitelistLEIAndVideoTSs(TCGroupDetails tcGroupDetails) {
089        tcGroupDetails.getWhitelistedTransferSyntaxes().clear();
090        tcGroupDetails.getWhitelistedTransferSyntaxes().add(UID.ImplicitVRLittleEndian);
091
092        for (String videoTsuid : DefaultTransferCapabilities.VIDEO_TSUIDS) {
093            tcGroupDetails.getWhitelistedTransferSyntaxes().add(videoTsuid);
094        }
095    }
096
097    public Map<String, TCGroupDetails> getScuTCs() {
098        return scuTCs;
099    }
100
101    public void setScuTCs(Map<String, TCGroupDetails> scuTCs) {
102        this.scuTCs = scuTCs;
103    }
104
105    public Map<String, TCGroupDetails> getScpTCs() {
106        return scpTCs;
107    }
108
109    public void setScpTCs(Map<String, TCGroupDetails> scpTCs) {
110        this.scpTCs = scpTCs;
111    }
112
113    @ConfigurableClass
114    public static class TCGroupDetails implements Serializable {
115
116        public TCGroupDetails() {
117        }
118
119        @ConfigurableProperty
120        private List<String> excludedTransferSyntaxes = new ArrayList<String>();
121
122        @ConfigurableProperty(
123                description = "If not empty, all the syntaxes but those specified by this parameter" +
124                "will be effectively removed from this AE's transfer capabilities")
125        private List<String> whitelistedTransferSyntaxes = new ArrayList<String>();
126
127        @ConfigurableProperty(
128                label = "Excluded SOP classes",
129                description = "This AE will include all transfer capabilities from the corresponding group, " +
130                        "except those with SOP classes specified here"
131        )
132        private List<String> excludedTransferCapabilities = new ArrayList<String>();
133
134        public List<String> getExcludedTransferSyntaxes() {
135            return excludedTransferSyntaxes;
136        }
137
138        public void setExcludedTransferSyntaxes(List<String> excludedTransferSyntaxes) {
139            this.excludedTransferSyntaxes = excludedTransferSyntaxes;
140        }
141
142        public List<String> getExcludedTransferCapabilities() {
143            return excludedTransferCapabilities;
144        }
145
146        public void setExcludedTransferCapabilities(List<String> excludedTransferCapabilities) {
147            this.excludedTransferCapabilities = excludedTransferCapabilities;
148        }
149
150        public List<String> getWhitelistedTransferSyntaxes() {
151            return whitelistedTransferSyntaxes;
152        }
153
154        public void setWhitelistedTransferSyntaxes(List<String> whitelistedTransferSyntaxes) {
155            this.whitelistedTransferSyntaxes = whitelistedTransferSyntaxes;
156        }
157    }
158
159    @Override
160    public void reconfigure(AEExtension from) {
161        TCGroupConfigAEExtension tcGroupConfigAEExtension = (TCGroupConfigAEExtension) from;
162        setScpTCs(tcGroupConfigAEExtension.getScpTCs());
163        setScuTCs(tcGroupConfigAEExtension.getScuTCs());
164    }
165
166
167    public static List<TransferCapability> getTCsForDefaultGroup(DefaultGroup group) {
168
169        ArrayList<TransferCapability> transferCapabilities;
170
171        switch (group) {
172            case STORAGE:
173                transferCapabilities = new ArrayList<TransferCapability>();
174                allTCToList(transferCapabilities, DefaultTransferCapabilities.IMAGE_CUIDS, null, DefaultTransferCapabilities.IMAGE_TSUIDS);
175                allTCToList(transferCapabilities, DefaultTransferCapabilities.VIDEO_CUIDS, null, DefaultTransferCapabilities.VIDEO_TSUIDS);
176                allTCToList(transferCapabilities, DefaultTransferCapabilities.OTHER_CUIDS, null, DefaultTransferCapabilities.OTHER_TSUIDS);
177                allTCToList(transferCapabilities, new String[]{UID.InstanceAvailabilityNotificationSOPClass, UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian);
178                return transferCapabilities;
179
180            case QUERY:
181                transferCapabilities = new ArrayList<TransferCapability>();
182                allTCToList(transferCapabilities, DefaultTransferCapabilities.QUERY_CUIDS, EnumSet.allOf(QueryOption.class), DefaultTransferCapabilities.OTHER_TSUIDS);
183                allTCToList(transferCapabilities, new String[]{UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian);
184                return transferCapabilities;
185
186            case RETRIEVE:
187                transferCapabilities = new ArrayList<TransferCapability>();
188                allTCToList(transferCapabilities, DefaultTransferCapabilities.RETRIEVE_CUIDS, EnumSet.of(QueryOption.RELATIONAL), DefaultTransferCapabilities.OTHER_TSUIDS);
189                allTCToList(transferCapabilities, new String[]{UID.CompositeInstanceRetrieveWithoutBulkDataGET, UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian);
190                return transferCapabilities;
191
192            case MWL:
193                transferCapabilities = new ArrayList<TransferCapability>();
194                allTCToList(transferCapabilities, new String[]{UID.ModalityWorklistInformationModelFIND, UID.VerificationSOPClass}, EnumSet.allOf(QueryOption.class), UID.ImplicitVRLittleEndian);
195                return transferCapabilities;
196
197            case PPS:
198                transferCapabilities = new ArrayList<TransferCapability>();
199                allTCToList(transferCapabilities, new String[]{UID.ModalityPerformedProcedureStepSOPClass, UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian);
200                return transferCapabilities;
201
202            case STORAGE_COMMITMENT:
203                transferCapabilities = new ArrayList<TransferCapability>();
204                allTCToList(transferCapabilities, new String[]{UID.StorageCommitmentPushModelSOPClass, UID.VerificationSOPClass}, null, UID.ImplicitVRLittleEndian);
205                return transferCapabilities;
206
207            default:
208                throw new RuntimeException("Group " + group + " is undefined");
209
210        }
211    }
212
213    private static void allTCToList(ArrayList<TransferCapability> transferCapabilities, String[] imageCuids, EnumSet<QueryOption> queryOptions, String... transferSyntaxes) {
214        for (String cuid : imageCuids) {
215            String name = UID.nameOf(cuid).replace('/', ' ');
216            TransferCapability tc = new TransferCapability(name, cuid, SCU, transferSyntaxes);
217            tc.setQueryOptions(queryOptions);
218            transferCapabilities.add(tc);
219        }
220    }
221
222}