001/* ***** BEGIN LICENSE BLOCK *****
002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003 *
004 * The contents of this file are subject to the Mozilla Public License Version
005 * 1.1 (the "License")), you may not use this file except in compliance with
006 * the License. You may obtain a copy of the License at
007 * http://www.mozilla.org/MPL/
008 *
009 * Software distributed under the License is distributed on an "AS IS" basis,
010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011 * for the specific language governing rights and limitations under the
012 * License.
013 *
014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in
015 * Java(TM), hosted at https://github.com/gunterze/dcm4che.
016 *
017 * The Initial Developer of the Original Code is
018 * Agfa Healthcare.
019 * Portions created by the Initial Developer are Copyright (C) 2012
020 * the Initial Developer. All Rights Reserved.
021 *
022 * Contributor(s):
023 * See @authors listed below
024 *
025 * Alternatively, the contents of this file may be used under the terms of
026 * either the GNU General Public License Version 2 or later (the "GPL"), or
027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
028 * in which case the provisions of the GPL or the LGPL are applicable instead
029 * of those above. If you wish to allow use of your version of this file only
030 * under the terms of either the GPL or the LGPL, and not to allow others to
031 * use your version of this file under the terms of the MPL, indicate your
032 * decision by deleting the provisions above and replace them with the notice
033 * and other provisions required by the GPL or the LGPL. If you do not delete
034 * the provisions above, a recipient may use your version of this file under
035 * the terms of any one of the MPL, the GPL or the LGPL.
036 *
037 * ***** END LICENSE BLOCK ***** */
038
039package org.dcm4che3.net;
040
041import org.dcm4che3.data.Tag;
042import org.dcm4che3.data.Attributes;
043import org.dcm4che3.util.StringUtils;
044import org.dcm4che3.util.TagUtils;
045import org.dcm4che3.util.UIDUtils;
046import org.slf4j.Logger;
047import org.slf4j.LoggerFactory;
048
049/**
050 * @author Gunter Zeilinger <gunterze@gmail.com>
051 *
052 */
053public enum Dimse {
054    C_STORE_RQ(0x0001, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
055            Tag.MessageID, ":C-STORE-RQ[pcid="),
056    C_STORE_RSP(0x8001, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
057            Tag.MessageIDBeingRespondedTo, ":C-STORE-RSP[pcid="),
058    C_GET_RQ(0x0010, Tag.AffectedSOPClassUID, 0,
059            Tag.MessageID, ":C-GET-RQ[pcid="),
060    C_GET_RSP(0x8010, Tag.AffectedSOPClassUID, 0,
061            Tag.MessageIDBeingRespondedTo, ":C-GET-RSP[pcid="),
062    C_FIND_RQ(0x0020, Tag.AffectedSOPClassUID, 0,
063            Tag.MessageID, ":C-FIND-RQ[pcid="),
064    C_FIND_RSP(0x8020, Tag.AffectedSOPClassUID, 0,
065            Tag.MessageIDBeingRespondedTo, ":C-FIND-RSP[pcid="),
066    C_MOVE_RQ(0x0021, Tag.AffectedSOPClassUID, 0,
067            Tag.MessageID, ":C-MOVE-RQ[pcid="),
068    C_MOVE_RSP(0x8021, Tag.AffectedSOPClassUID, 0,
069            Tag.MessageIDBeingRespondedTo, ":C-MOVE-RSP[pcid="),
070    C_ECHO_RQ(0x0030, Tag.AffectedSOPClassUID, 0,
071            Tag.MessageID, ":C-ECHO-RQ[pcid="),
072    C_ECHO_RSP(0x8030, Tag.AffectedSOPClassUID, 0,
073            Tag.MessageIDBeingRespondedTo, ":C-ECHO-RSP[pcid="),
074    N_EVENT_REPORT_RQ(0x0100, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
075            Tag.MessageID, ":N-EVENT-REPORT-RQ[pcid="),
076    N_EVENT_REPORT_RSP(0x8100, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
077            Tag.MessageIDBeingRespondedTo, ":N-EVENT-REPORT-RSP[pcid="),
078    N_GET_RQ(0x0110, Tag.RequestedSOPClassUID, Tag.RequestedSOPInstanceUID,
079            Tag.MessageID, ":N-GET-RQ[pcid="),
080    N_GET_RSP(0x8110, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
081            Tag.MessageIDBeingRespondedTo, ":N-GET-RSP[pcid="),
082    N_SET_RQ(0x0120, Tag.RequestedSOPClassUID, Tag.RequestedSOPInstanceUID,
083            Tag.MessageID, ":N-SET-RQ[pcid="),
084    N_SET_RSP(0x8120, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
085            Tag.MessageIDBeingRespondedTo, ":N-SET-RSP[pcid="),
086    N_ACTION_RQ(0x0130, Tag.RequestedSOPClassUID, Tag.RequestedSOPInstanceUID,
087            Tag.MessageID, ":N-ACTION-RQ[pcid="),
088    N_ACTION_RSP(0x8130, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
089            Tag.MessageIDBeingRespondedTo, ":N-ACTION-RSP[pcid="),
090    N_CREATE_RQ(0x0140, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
091            Tag.MessageID, ":N-CREATE-RQ[pcid="),
092    N_CREATE_RSP(0x8140, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
093            Tag.MessageIDBeingRespondedTo, ":N-CREATE-RSP[pcid="),
094    N_DELETE_RQ(0x0150, Tag.RequestedSOPClassUID, Tag.RequestedSOPInstanceUID,
095            Tag.MessageID, ":N-DELETE-RQ[pcid="),
096    N_DELETE_RSP(0x8150, Tag.AffectedSOPClassUID, Tag.AffectedSOPInstanceUID,
097            Tag.MessageIDBeingRespondedTo, ":N-DELETE-RSP[pcid="),
098    C_CANCEL_RQ(0x0FFF, 0, 0, Tag.MessageIDBeingRespondedTo, ":C-CANCEL-RQ[pcid=");
099
100    public static final Logger LOG = LoggerFactory.getLogger(Dimse.class);
101
102    private final int commandField;
103    private final int tagOfSOPClassUID;
104    private final int tagOfSOPInstanceUID;
105    private final int tagOfMessageID;
106    private final String prompt;
107
108    private Dimse(int cmdField, int tagOfSOPClassUID, int tagOfSOPInstanceUID,
109            int tagOfMessageID, String prompt) {
110        this.commandField = cmdField;
111        this.tagOfSOPClassUID = tagOfSOPClassUID;
112        this.tagOfSOPInstanceUID = tagOfSOPInstanceUID;
113        this.tagOfMessageID = tagOfMessageID;
114        this.prompt = prompt;
115    }
116
117    public int commandField() {
118        return commandField;
119    }
120
121    public int tagOfSOPClassUID() {
122        return tagOfSOPClassUID;
123    }
124
125    public int tagOfSOPInstanceUID() {
126        return tagOfSOPInstanceUID;
127    }
128
129    public boolean isRSP() {
130        return (commandField & 0x8000) != 0;
131    }
132
133    public boolean isRetrieveRQ() {
134        return this == C_GET_RQ || this == C_MOVE_RQ;
135    }
136
137    public boolean isRetrieveRSP() {
138        return this == C_GET_RSP || this == C_MOVE_RSP;
139    }
140
141    public boolean isCService() {
142        return (commandField & 0x100) == 0;
143    }
144
145    public int commandFieldOfRSP() {
146        return commandField | 0x8000;
147    }
148
149    public static Dimse valueOf(int commandField) {
150        switch(commandField) {
151        case 0x0001:
152            return C_STORE_RQ;
153        case 0x8001:
154            return C_STORE_RSP;
155        case 0x0010:
156            return C_GET_RQ;
157        case 0x8010:
158            return C_GET_RSP;
159        case 0x0020:
160            return C_FIND_RQ;
161        case 0x8020:
162            return C_FIND_RSP;
163        case 0x0021:
164            return C_MOVE_RQ;
165        case 0x8021:
166            return C_MOVE_RSP;
167        case 0x0030:
168            return C_ECHO_RQ;
169        case 0x8030:
170            return C_ECHO_RSP;
171        case 0x0100:
172            return N_EVENT_REPORT_RQ;
173        case 0x8100:
174            return N_EVENT_REPORT_RSP;
175        case 0x0110:
176            return N_GET_RQ;
177        case 0x8110:
178            return N_GET_RSP;
179        case 0x0120:
180            return N_SET_RQ;
181        case 0x8120:
182            return N_SET_RSP;
183        case 0x0130:
184            return N_ACTION_RQ;
185        case 0x8130:
186            return N_ACTION_RSP;
187        case 0x0140:
188            return N_CREATE_RQ;
189        case 0x8140:
190            return N_CREATE_RSP;
191        case 0x0150:
192            return N_DELETE_RQ;
193        case 0x8150:
194            return N_DELETE_RSP;
195        case 0x0FFF:
196            return C_CANCEL_RQ;
197        default:
198            throw new IllegalArgumentException("commandField: " + commandField);
199        }
200    }
201
202    public String toString(Attributes cmdAttrs, int pcid, String tsuid) {
203        StringBuilder sb = new StringBuilder();
204        sb.append(cmdAttrs.getInt(tagOfMessageID, -1)).append(prompt).append(pcid);
205        switch (this) {
206        case C_STORE_RQ:
207            promptIntTo(cmdAttrs, ", prior=", Tag.Priority, sb);
208            promptMoveOriginatorTo(cmdAttrs, sb);
209            break;
210        case C_GET_RQ:
211            promptIntTo(cmdAttrs, ", prior=", Tag.Priority, sb);
212            promptAttributeIdentifierListTo(cmdAttrs, sb);
213            break;
214        case C_FIND_RQ:
215        case C_MOVE_RQ:
216            promptIntTo(cmdAttrs, ", prior=", Tag.Priority, sb);
217            break;
218        case C_GET_RSP:
219        case C_MOVE_RSP:
220            promptNumberOfSubOpsTo(cmdAttrs, sb);
221            break;
222        case N_EVENT_REPORT_RQ:
223        case N_EVENT_REPORT_RSP:
224            promptIntTo(cmdAttrs, ", eventID=", Tag.EventTypeID, sb);
225            break;
226        case N_ACTION_RQ:
227        case N_ACTION_RSP:
228            promptIntTo(cmdAttrs, ", actionID=", Tag.ActionTypeID, sb);
229            break;
230        }
231        if (isRSP()) {
232            sb.append(", status=")
233              .append(Integer.toHexString(cmdAttrs.getInt(Tag.Status, -1)))
234              .append('H');
235            promptIntTo(cmdAttrs, ", errorID=", Tag.ErrorID, sb);
236            promptStringTo(cmdAttrs, ", errorComment=", Tag.ErrorComment, sb);
237            promptAttributeIdentifierListTo(cmdAttrs, sb);
238        }
239        promptUIDTo(cmdAttrs, "  cuid=", tagOfSOPClassUID, sb);
240        promptUIDTo(cmdAttrs, "  iuid=", tagOfSOPInstanceUID, sb);
241        promptUIDTo("  tsuid=", tsuid, sb);
242        return sb.toString();
243    }
244
245    private static void promptIntTo(Attributes cmd, String name, int tag,
246            StringBuilder sb) {
247        int val = cmd.getInt(tag, 0);
248        if (val != 0 || cmd.containsValue(tag))
249            sb.append(name).append(val);
250    }
251
252    private static void promptStringTo(Attributes cmd, String name, int tag,
253            StringBuilder sb) {
254        String s = cmd.getString(tag, null);
255        if (s != null)
256            sb.append(name).append(s);
257    }
258
259    private static void promptUIDTo(Attributes cmd, String name, int tag,
260            StringBuilder sb) {
261        if (tag != 0) {
262            String uid = cmd.getString(tag, null);
263            if (uid != null)
264                promptUIDTo(name, uid, sb);
265        }
266    }
267
268    private static void promptUIDTo(String name, String uid, StringBuilder sb) {
269        sb.append(StringUtils.LINE_SEPARATOR).append(name);
270        UIDUtils.promptTo(uid, sb);
271    }
272
273    private static void promptMoveOriginatorTo(Attributes cmd, StringBuilder sb) {
274        String aet = cmd.getString(Tag.MoveOriginatorApplicationEntityTitle,
275                null);
276        if (aet != null)
277            sb.append(StringUtils.LINE_SEPARATOR)
278              .append("  orig=")
279              .append(aet)
280              .append(" >> ")
281              .append(cmd.getInt(Tag.MoveOriginatorMessageID, -1))
282              .append(":C-MOVE-RQ");
283    }
284
285    private static void promptAttributeIdentifierListTo(Attributes cmd,
286            StringBuilder sb) {
287        int[] tags = cmd.getInts(Tag.AttributeIdentifierList);
288        if (tags == null)
289            return;
290
291        sb.append(StringUtils.LINE_SEPARATOR).append("  tags=[");
292        if (tags.length > 0) {
293            for (int tag : tags)
294                sb.append(TagUtils.toString(tag)).append(", ");
295            sb.setLength(sb.length()-2);
296        }
297        sb.append(']');
298    }
299
300    private static void promptNumberOfSubOpsTo(Attributes cmd, StringBuilder sb) {
301        promptIntTo(cmd, ", remaining=", Tag.NumberOfRemainingSuboperations, sb);
302        promptIntTo(cmd, ", completed=", Tag.NumberOfCompletedSuboperations, sb);
303        promptIntTo(cmd, ", failed=", Tag.NumberOfFailedSuboperations, sb);
304        promptIntTo(cmd, ", warning=", Tag.NumberOfWarningSuboperations, sb);
305    }
306}