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}