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.pdu; 040 041import java.util.ArrayList; 042import java.util.Collection; 043import java.util.Collections; 044import java.util.LinkedHashMap; 045import java.util.List; 046 047import org.dcm4che3.data.UID; 048import org.dcm4che3.data.Implementation; 049import org.dcm4che3.net.Connection; 050import org.dcm4che3.util.IntHashMap; 051import org.dcm4che3.util.StringUtils; 052import org.dcm4che3.util.UIDUtils; 053 054/** 055 * @author Gunter Zeilinger <gunterze@gmail.com> 056 * 057 */ 058public abstract class AAssociateRQAC { 059 060 protected byte[] reservedBytes = new byte[32]; 061 protected int protocolVersion = 1; 062 protected int maxPDULength = Connection.DEF_MAX_PDU_LENGTH; 063 protected int maxOpsInvoked = Connection.SYNCHRONOUS_MODE; 064 protected int maxOpsPerformed = Connection.SYNCHRONOUS_MODE; 065 protected String calledAET; 066 protected String callingAET; 067 protected String applicationContext = UID.DICOMApplicationContextName; 068 protected String implClassUID = Implementation.getClassUID(); 069 protected String implVersionName = Implementation.getVersionName(); 070 protected UserIdentityRQ userIdentityRQ; 071 protected UserIdentityAC userIdentityAC; 072 protected final ArrayList<PresentationContext> 073 pcs = new ArrayList<PresentationContext>(); 074 protected final IntHashMap<PresentationContext> 075 pcidMap = new IntHashMap<PresentationContext>(); 076 protected final LinkedHashMap<String, RoleSelection> 077 roleSelMap = new LinkedHashMap<String, RoleSelection>(); 078 protected final LinkedHashMap<String, ExtendedNegotiation> 079 extNegMap = new LinkedHashMap<String, ExtendedNegotiation>(); 080 protected final LinkedHashMap<String, CommonExtendedNegotiation> 081 commonExtNegMap = new LinkedHashMap<String, CommonExtendedNegotiation>(); 082 083 public void checkCallingAET() { 084 if (callingAET == null) 085 throw new IllegalStateException("Calling AET not initalized"); 086 } 087 088 public void checkCalledAET() { 089 if (calledAET == null) 090 throw new IllegalStateException("Called AET not initalized"); 091 } 092 093 public final int getProtocolVersion() { 094 return protocolVersion; 095 } 096 097 public final void setProtocolVersion(int protocolVersion) { 098 this.protocolVersion = protocolVersion; 099 } 100 101 public final byte[] getReservedBytes() { 102 return reservedBytes.clone(); 103 } 104 105 public final void setReservedBytes(byte[] reservedBytes) { 106 if (reservedBytes.length != 32) 107 throw new IllegalArgumentException("reservedBytes.length: " 108 + reservedBytes.length); 109 System.arraycopy(reservedBytes, 0, this.reservedBytes, 0, 32); 110 } 111 112 public final String getCalledAET() { 113 return calledAET; 114 } 115 116 public final void setCalledAET(String calledAET) { 117 if (calledAET.length() > 16) 118 throw new IllegalArgumentException("calledAET: " + calledAET); 119 this.calledAET = calledAET; 120 } 121 122 public final String getCallingAET() { 123 return callingAET; 124 } 125 126 public final void setCallingAET(String callingAET) { 127 if (callingAET.length() > 16) 128 throw new IllegalArgumentException("callingAET: " + callingAET); 129 this.callingAET = callingAET; 130 } 131 132 public final String getApplicationContext() { 133 return applicationContext; 134 } 135 136 public final void setApplicationContext(String applicationContext) { 137 if (applicationContext == null) 138 throw new NullPointerException(); 139 140 this.applicationContext = applicationContext; 141 } 142 143 public final int getMaxPDULength() { 144 return maxPDULength; 145 } 146 147 public final void setMaxPDULength(int maxPDULength) { 148 this.maxPDULength = maxPDULength; 149 } 150 151 public final int getMaxOpsInvoked() { 152 return maxOpsInvoked; 153 } 154 155 public final void setMaxOpsInvoked(int maxOpsInvoked) { 156 this.maxOpsInvoked = maxOpsInvoked; 157 } 158 159 public final int getMaxOpsPerformed() { 160 return maxOpsPerformed; 161 } 162 163 public final void setMaxOpsPerformed(int maxOpsPerformed) { 164 this.maxOpsPerformed = maxOpsPerformed; 165 } 166 167 public final boolean isAsyncOps() { 168 return maxOpsInvoked != 1 || maxOpsPerformed != 1; 169 } 170 171 public final String getImplClassUID() { 172 return implClassUID; 173 } 174 175 public final void setImplClassUID(String implClassUID) { 176 if (implClassUID == null) 177 throw new NullPointerException(); 178 179 this.implClassUID = implClassUID; 180 } 181 182 public final String getImplVersionName() { 183 return implVersionName; 184 } 185 186 public final void setImplVersionName(String implVersionName) { 187 this.implVersionName = implVersionName; 188 } 189 190 public final UserIdentityRQ getUserIdentityRQ() { 191 return userIdentityRQ; 192 } 193 194 public void setUserIdentityRQ(UserIdentityRQ userIdentityRQ) { 195 this.userIdentityRQ = userIdentityRQ; 196 } 197 198 public final UserIdentityAC getUserIdentityAC() { 199 return userIdentityAC; 200 } 201 202 public void setUserIdentityAC(UserIdentityAC userIdentityAC) { 203 this.userIdentityAC = userIdentityAC; 204 } 205 206 public List<PresentationContext> getPresentationContexts() { 207 return Collections.unmodifiableList(pcs); 208 } 209 210 public int getNumberOfPresentationContexts() { 211 return pcs.size(); 212 } 213 214 public PresentationContext getPresentationContext(int pcid) { 215 return pcidMap.get(pcid); 216 } 217 218 public void addPresentationContext(PresentationContext pc) { 219 int pcid = pc.getPCID(); 220 if (pcidMap.containsKey(pcid)) 221 throw new IllegalStateException( 222 "Already contains Presentation Context with pid: " 223 + pcid); 224 pcidMap.put(pcid, pc); 225 pcs.add(pc); 226 } 227 228 public boolean removePresentationContext(PresentationContext pc) { 229 if (!pcs.remove(pc)) 230 return false; 231 232 pcidMap.remove(pc.getPCID()); 233 return true; 234 } 235 236 public Collection<RoleSelection> getRoleSelections() { 237 return Collections.unmodifiableCollection(roleSelMap.values()); 238 } 239 240 public RoleSelection getRoleSelectionFor(String cuid) { 241 return roleSelMap.get(cuid); 242 } 243 244 public RoleSelection addRoleSelection(RoleSelection rs) { 245 return roleSelMap.put(rs.getSOPClassUID(), rs); 246 } 247 248 public RoleSelection removeRoleSelectionFor(String cuid) { 249 return roleSelMap.remove(cuid); 250 } 251 252 public Collection<ExtendedNegotiation> getExtendedNegotiations() { 253 return Collections.unmodifiableCollection(extNegMap.values()); 254 } 255 256 public ExtendedNegotiation getExtNegotiationFor(String cuid) { 257 return extNegMap.get(cuid); 258 } 259 260 public ExtendedNegotiation addExtendedNegotiation(ExtendedNegotiation extNeg) { 261 return extNegMap.put(extNeg.getSOPClassUID(), extNeg); 262 } 263 264 public ExtendedNegotiation removeExtendedNegotiationFor(String cuid) { 265 return extNegMap.remove(cuid); 266 } 267 268 public Collection<CommonExtendedNegotiation> getCommonExtendedNegotiations() { 269 return Collections.unmodifiableCollection(commonExtNegMap.values()); 270 } 271 272 public CommonExtendedNegotiation getCommonExtendedNegotiationFor(String cuid) { 273 return commonExtNegMap.get(cuid); 274 } 275 276 public CommonExtendedNegotiation addCommonExtendedNegotiation( 277 CommonExtendedNegotiation extNeg) { 278 return commonExtNegMap.put(extNeg.getSOPClassUID(), extNeg); 279 } 280 281 public CommonExtendedNegotiation removeCommonExtendedNegotiationFor( 282 String cuid) { 283 return commonExtNegMap.remove(cuid); 284 } 285 286 public int length() { 287 int len = 68; // Fix AA-RQ/AC PDU fields 288 len += 4 + applicationContext.length(); 289 for (PresentationContext pc : pcs) { 290 len += 4 + pc.length(); 291 } 292 len += 4 + userInfoLength(); 293 return len; 294 } 295 296 public int userInfoLength() { 297 int len = 8; // Max Length Sub-Item 298 len += 4 + implClassUID.length(); 299 if (isAsyncOps()) 300 len += 8; // Asynchronous Operations Window Sub-Item 301 for (RoleSelection rs : roleSelMap.values()) { 302 len += 4 + rs.length(); 303 } 304 if (implVersionName != null) 305 len += 4 + implVersionName.length(); 306 for (ExtendedNegotiation en : extNegMap.values()) { 307 len += 4 + en.length(); 308 } 309 for (CommonExtendedNegotiation cen : commonExtNegMap.values()) { 310 len += 4 + cen.length(); 311 } 312 if (userIdentityRQ != null) 313 len += 4 + userIdentityRQ.length(); 314 if (userIdentityAC != null) 315 len += 4 + userIdentityAC.length(); 316 return len; 317 } 318 319 protected StringBuilder promptTo(String header, StringBuilder sb) { 320 sb.append(header) 321 .append(StringUtils.LINE_SEPARATOR) 322 .append(" calledAET: ").append(calledAET) 323 .append(StringUtils.LINE_SEPARATOR) 324 .append(" callingAET: ").append(callingAET) 325 .append(StringUtils.LINE_SEPARATOR) 326 .append(" applicationContext: "); 327 UIDUtils.promptTo(applicationContext, sb) 328 .append(StringUtils.LINE_SEPARATOR) 329 .append(" implClassUID: ").append(implClassUID) 330 .append(StringUtils.LINE_SEPARATOR) 331 .append(" implVersionName: ").append(implVersionName) 332 .append(StringUtils.LINE_SEPARATOR) 333 .append(" maxPDULength: ").append(maxPDULength) 334 .append(StringUtils.LINE_SEPARATOR) 335 .append(" maxOpsInvoked/maxOpsPerformed: ") 336 .append(maxOpsInvoked).append("/").append(maxOpsPerformed) 337 .append(StringUtils.LINE_SEPARATOR); 338 if (userIdentityRQ != null) 339 userIdentityRQ.promptTo(sb).append(StringUtils.LINE_SEPARATOR); 340 if (userIdentityAC != null) 341 userIdentityAC.promptTo(sb).append(StringUtils.LINE_SEPARATOR); 342 for (PresentationContext pc : pcs) 343 pc.promptTo(sb).append(StringUtils.LINE_SEPARATOR); 344 for (RoleSelection rs : roleSelMap.values()) 345 rs.promptTo(sb).append(StringUtils.LINE_SEPARATOR); 346 for (ExtendedNegotiation extNeg : extNegMap.values()) 347 extNeg.promptTo(sb).append(StringUtils.LINE_SEPARATOR); 348 for (CommonExtendedNegotiation extNeg : commonExtNegMap.values()) 349 extNeg.promptTo(sb).append(StringUtils.LINE_SEPARATOR); 350 return sb.append("]"); 351 } 352}