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) 2011 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.data.VR; 044import org.dcm4che3.util.UIDUtils; 045 046/** 047 * @author Gunter Zeilinger <gunterze@gmail.com> 048 * 049 */ 050public class Commands { 051 052 public static final int NO_DATASET = 0x0101; 053 private static int withDatasetType = 0x0000; 054 055 public static Attributes mkCStoreRQ(int msgId, String cuid, String iuid, 056 int priority) { 057 Attributes rq = mkRQ(msgId, 0x0001, withDatasetType); 058 rq.setString(Tag.AffectedSOPClassUID, VR.UI, cuid); 059 rq.setString(Tag.AffectedSOPInstanceUID, VR.UI, iuid); 060 rq.setInt(Tag.Priority, VR.US, priority); 061 return rq; 062 } 063 064 public static Attributes mkCStoreRQ(int msgId, String cuid, String iuid, 065 int priority, String moveOriginatorAET, int moveOriginatorMsgId) { 066 Attributes rq = mkCStoreRQ(msgId, cuid, iuid, priority); 067 rq.setString(Tag.MoveOriginatorApplicationEntityTitle, VR.AE, 068 moveOriginatorAET); 069 rq.setInt(Tag.MoveOriginatorMessageID, VR.US, moveOriginatorMsgId); 070 return rq; 071 } 072 073 public static Attributes mkCStoreRSP(Attributes cmd, int status) { 074 return mkRSP(cmd, status, Dimse.C_STORE_RQ); 075 } 076 077 public static Attributes mkCFindRQ(int msgId, String cuid, int priority) { 078 Attributes rq = mkRQ(msgId, 0x0020, withDatasetType); 079 rq.setString(Tag.AffectedSOPClassUID, VR.UI, cuid); 080 rq.setInt(Tag.Priority, VR.US, priority); 081 return rq; 082 } 083 084 public static Attributes mkCFindRSP(Attributes cmd, int status) { 085 return mkRSP(cmd, status, Dimse.C_FIND_RQ); 086 } 087 088 public static Attributes mkCGetRQ(int msgId, String cuid, int priority) { 089 Attributes rq = mkRQ(msgId, 0x0010, withDatasetType); 090 rq.setString(Tag.AffectedSOPClassUID, VR.UI, cuid); 091 rq.setInt(Tag.Priority, VR.US, priority); 092 return rq; 093 } 094 095 public static Attributes mkCGetRSP(Attributes cmd, int status) { 096 return mkRSP(cmd, status, Dimse.C_GET_RQ); 097 } 098 099 public static Attributes mkCMoveRQ(int msgId, String cuid, int priority, 100 String destination) { 101 Attributes rq = mkRQ(msgId, 0x0021, withDatasetType); 102 rq.setString(Tag.AffectedSOPClassUID, VR.UI, cuid); 103 rq.setInt(Tag.Priority, VR.US, priority); 104 rq.setString(Tag.MoveDestination, VR.AE, destination); 105 return rq; 106 } 107 108 public static Attributes mkCMoveRSP(Attributes cmd, int status) { 109 return mkRSP(cmd, status, Dimse.C_MOVE_RQ); 110 } 111 112 public static Attributes mkCCancelRQ(int msgId) { 113 Attributes rq = new Attributes(); 114 rq.setInt(Tag.CommandField, VR.US, Dimse.C_CANCEL_RQ.commandField()); 115 rq.setInt(Tag.CommandDataSetType, VR.US, NO_DATASET); 116 rq.setInt(Tag.MessageIDBeingRespondedTo, VR.US, msgId); 117 return rq; 118 } 119 120 public static Attributes mkCEchoRQ(int msgId, String cuid) { 121 Attributes rq = mkRQ(msgId, 0x0030, NO_DATASET); 122 rq.setString(Tag.AffectedSOPClassUID, VR.UI, cuid); 123 return rq; 124 } 125 126 public static Attributes mkEchoRSP(Attributes cmd, int status) { 127 return mkRSP(cmd, status, Dimse.C_ECHO_RQ); 128 } 129 130 public static Attributes mkNEventReportRQ(int msgId, String cuid, 131 String iuid, int eventTypeID, Attributes data) { 132 Attributes rq = mkRQ(msgId, 0x0100, 133 data == null ? NO_DATASET : withDatasetType); 134 rq.setString(Tag.AffectedSOPClassUID, VR.UI, cuid); 135 rq.setString(Tag.AffectedSOPInstanceUID, VR.UI, iuid); 136 rq.setInt(Tag.EventTypeID, VR.US, eventTypeID); 137 return rq; 138 } 139 140 public static Attributes mkNEventReportRSP(Attributes cmd, int status) { 141 return mkRSP(cmd, status, Dimse.N_EVENT_REPORT_RQ); 142 } 143 144 public static Attributes mkNGetRQ(int msgId, String cuid, String iuid, 145 int[] tags) { 146 Attributes rq = mkRQ(msgId, 0x0110, NO_DATASET); 147 rq.setString(Tag.RequestedSOPClassUID, VR.UI, cuid); 148 rq.setString(Tag.RequestedSOPInstanceUID, VR.UI, iuid); 149 if (tags != null) 150 rq.setInt(Tag.AttributeIdentifierList, VR.AT, tags); 151 return rq; 152 } 153 154 public static Attributes mkNGetRSP(Attributes cmd, int status) { 155 return mkRSP(cmd, status, Dimse.N_GET_RQ); 156 } 157 158 public static Attributes mkNSetRQ(int msgId, String cuid, String iuid) { 159 Attributes rq = mkRQ(msgId, 0x0120, withDatasetType); 160 rq.setString(Tag.RequestedSOPClassUID, VR.UI, cuid); 161 rq.setString(Tag.RequestedSOPInstanceUID, VR.UI, iuid); 162 return rq; 163 } 164 165 public static Attributes mkNSetRSP(Attributes cmd, int status) { 166 return mkRSP(cmd, status, Dimse.N_SET_RQ); 167 } 168 169 public static Attributes mkNActionRQ(int msgId, String cuid, 170 String iuid, int actionTypeID, Attributes data) { 171 Attributes rq = mkRQ(msgId, 0x0130, 172 data == null ? NO_DATASET : withDatasetType); 173 rq.setString(Tag.RequestedSOPClassUID, VR.UI, cuid); 174 rq.setString(Tag.RequestedSOPInstanceUID, VR.UI, iuid); 175 rq.setInt(Tag.ActionTypeID, VR.US, actionTypeID); 176 return rq; 177 } 178 179 public static Attributes mkNActionRSP(Attributes cmd, int status) { 180 return mkRSP(cmd, status, Dimse.N_ACTION_RQ); 181 } 182 183 public static Attributes mkNCreateRQ(int msgId, String cuid, String iuid) { 184 Attributes rq = mkRQ(msgId, 0x0140, withDatasetType); 185 rq.setString(Tag.AffectedSOPClassUID, VR.UI, cuid); 186 if (iuid != null) 187 rq.setString(Tag.AffectedSOPInstanceUID, VR.UI, iuid); 188 return rq; 189 } 190 191 public static Attributes mkNCreateRSP(Attributes cmd, int status) { 192 String iuid = cmd.getString(Tag.AffectedSOPInstanceUID); 193 if (iuid == null) 194 cmd.setString(Tag.AffectedSOPInstanceUID, VR.UI, UIDUtils.createUID()); 195 return mkRSP(cmd, status, Dimse.N_CREATE_RQ); 196 } 197 198 public static Attributes mkNDeleteRQ(int msgId, String cuid, String iuid) { 199 Attributes rq = mkRQ(msgId, 0x0150, NO_DATASET); 200 rq.setString(Tag.RequestedSOPClassUID, VR.UI, cuid); 201 rq.setString(Tag.RequestedSOPInstanceUID, VR.UI, iuid); 202 return rq; 203 } 204 205 public static Attributes mkNDeleteRSP(Attributes cmd, int status) { 206 return mkRSP(cmd, status, Dimse.N_DELETE_RQ); 207 } 208 209 private static Attributes mkRQ(int msgId, int cmdField, int datasetType) { 210 Attributes rsp = new Attributes(); 211 rsp.setInt(Tag.MessageID, VR.US, msgId); 212 rsp.setInt(Tag.CommandField, VR.US, cmdField); 213 rsp.setInt(Tag.CommandDataSetType, VR.US, datasetType); 214 return rsp; 215 } 216 217 public static Attributes mkRSP(Attributes rq, int status, Dimse rqCmd) { 218 Attributes rsp = new Attributes(); 219 rsp.setInt(Tag.CommandField, VR.US, rqCmd.commandFieldOfRSP()); 220 rsp.setInt(Tag.Status, VR.US, status); 221 rsp.setInt(Tag.MessageIDBeingRespondedTo, VR.US, 222 rq.getInt(Tag.MessageID, 0)); 223 rsp.setString(Tag.AffectedSOPClassUID, VR.UI, 224 rq.getString(rqCmd.tagOfSOPClassUID())); 225 int tagOfIUID = rqCmd.tagOfSOPInstanceUID(); 226 if (tagOfIUID != 0) 227 rsp.setString(Tag.AffectedSOPInstanceUID, VR.UI, 228 rq.getString(tagOfIUID)); 229 return rsp; 230 } 231 232 public static void initNumberOfSuboperations(Attributes rsp, 233 int remaining) { 234 rsp.setInt(Tag.NumberOfRemainingSuboperations, VR.US, remaining); 235 rsp.setInt(Tag.NumberOfCompletedSuboperations, VR.US, 0); 236 rsp.setInt(Tag.NumberOfFailedSuboperations, VR.US, 0); 237 rsp.setInt(Tag.NumberOfWarningSuboperations, VR.US, 0); 238 } 239 240 public static void incNumberOfSuboperations(int tag, Attributes rsp) { 241 synchronized (rsp) { 242 rsp.setInt(tag, VR.US, rsp.getInt(tag, 0) + 1); 243 rsp.setInt(Tag.NumberOfRemainingSuboperations, VR.US, 244 rsp.getInt(Tag.NumberOfRemainingSuboperations, 1) - 1); 245 } 246 } 247 248 public static int getWithDatasetType() { 249 return withDatasetType; 250 } 251 252 public static void setWithDatasetType(int withDatasetType) { 253 if (withDatasetType == NO_DATASET 254 || (withDatasetType & 0xffff0000) != 0) 255 throw new IllegalArgumentException("withDatasetType: " 256 + Integer.toHexString(withDatasetType) + "H"); 257 Commands.withDatasetType = withDatasetType; 258 } 259 260 public static boolean hasDataset(Attributes cmd) { 261 return cmd.getInt(Tag.CommandDataSetType, 0) != NO_DATASET; 262 } 263 264}