/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is part of dcm4che, an implementation of DICOM(TM) in
* Java(TM), hosted at https://github.com/gunterze/dcm4che.
*
* The Initial Developer of the Original Code is
* Agfa Healthcare.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* See @authors listed below
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.dcm4che3.net;
import java.io.*;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Set;
import org.dcm4che3.conf.core.api.ConfigurableClass;
import org.dcm4che3.conf.core.api.ConfigurableProperty;
import org.dcm4che3.conf.core.api.LDAP;
import org.dcm4che3.data.UID;
import org.dcm4che3.util.StringUtils;
import org.dcm4che3.util.UIDUtils;
/**
* DICOM Standard, Part 15, Annex H: Transfer Capability - The description of
* the SOP classes and syntaxes supported by a Network AE.
* <p>
* An instance of the <code>TransferCapability</code> class describes the
* DICOM transfer capabilities of an SCU or SCP in terms of a single
* presentation syntax. This includes the role selection (SCU or SCP), the
* acceptable transfer syntaxes for a given SOP Class, and any extra
* information.
*
* @author Gunter Zeilinger <gunterze@gmail.com>
*
*/
@LDAP(objectClasses = {"dicomTransferCapability", "dcmTransferCapability"})
@ConfigurableClass
public class TransferCapability implements Serializable {
private static final long serialVersionUID = 6386251434418693778L;
public enum Role { SCU, SCP }
private ApplicationEntity ae;
@ConfigurableProperty(name="cn")
private String commonName;
@ConfigurableProperty(name="dicomSOPClass")
private String sopClass;
@ConfigurableProperty(name="dicomTransferRole")
private Role role;
@ConfigurableProperty(name="dicomTransferSyntax")
private String[] transferSyntaxes;
@LDAP( booleanBasedEnumStorageOptions = {"dcmRelationalQueries","dcmCombinedDateTimeMatching","dcmFuzzySemanticMatching","dcmTimezoneQueryAdjustment"},
noContainerNode = true)
@ConfigurableProperty(name = "dcmQueryOptions", enumRepresentation = ConfigurableProperty.EnumRepresentation.ORDINAL)
private EnumSet<QueryOption> queryOptions;
@LDAP(noContainerNode = true)
@ConfigurableProperty(name = "dcmStorageOptions")
private StorageOptions storageOptions;
public TransferCapability() {
this(null, UID.VerificationSOPClass, Role.SCU, UID.ImplicitVRLittleEndian);
}
public TransferCapability(String commonName, String sopClass, Role role,
String... transferSyntaxes) {
setCommonName(commonName);
setSopClass(sopClass);
setRole(role);
setTransferSyntaxes(transferSyntaxes);
}
public void setApplicationEntity(ApplicationEntity ae) {
if (ae != null) {
if (this.ae != null)
throw new IllegalStateException("already owned by AE " +
this.ae.getAETitle());
}
this.ae = ae;
}
/**
* get the name of the Transfer Capability object. Can be a meaningful name
* or any unique sequence of characters.
*
* @return A String containing the common name.
*/
public String getCommonName() {
return commonName;
}
public void setCommonName(String commonName) {
this.commonName = commonName;
}
/**
* Get the role for this <code>TransferCapability</code>instance.
*
* @return Role (SCU or SCP) for this <code>TransferCapability</code>instance
*/
public Role getRole() {
return role;
}
public void setRole(Role role) {
if (role == null)
throw new NullPointerException();
if (this.role == role)
return;
ApplicationEntity ae = this.ae;
if (ae != null)
ae.removeTransferCapabilityFor(sopClass, this.role);
this.role = role;
if (ae != null)
ae.addTransferCapability(this);
}
/**
* Get the SOP Class of this Transfer Capability object.
*
* @return A String containing the SOP Class UID.
*/
public String getSopClass() {
return sopClass;
}
public void setSopClass(String sopClass) {
if (sopClass.isEmpty())
throw new IllegalArgumentException("empty sopClass");
if (sopClass.equals(this.sopClass))
return;
ApplicationEntity ae = this.ae;
if (ae != null)
ae.removeTransferCapabilityFor(sopClass, this.role);
this.sopClass = sopClass;
if (ae != null)
ae.addTransferCapability(this);
}
/**
* Get the transfer syntax(es) that may be requested as an SCU or that are
* offered as an SCP.
*
* @return list of transfer syntaxes.
*/
public String[] getTransferSyntaxes() {
return transferSyntaxes;
}
public void setTransferSyntaxes(String... transferSyntaxes) {
if (transferSyntaxes.length == 0)
throw new IllegalArgumentException("missing transferSyntax");
for (String ts : transferSyntaxes)
if (ts.isEmpty())
throw new IllegalArgumentException("empty transferSyntax");
this.transferSyntaxes = transferSyntaxes;
}
public boolean containsTransferSyntax(String ts) {
if ("*".equals(transferSyntaxes[0]))
return true;
for (String s : transferSyntaxes)
if (ts.equals(s))
return true;
return false;
}
public void setQueryOptions(EnumSet<QueryOption> queryOptions) {
this.queryOptions = EnumSet.noneOf(QueryOption.class);
if (queryOptions != null)
this.queryOptions.addAll(queryOptions);
}
public EnumSet<QueryOption> getQueryOptions() {
return queryOptions;
}
public void setStorageOptions(StorageOptions storageOptions) {
this.storageOptions = storageOptions;
}
public StorageOptions getStorageOptions() {
return storageOptions;
}
@Override
public String toString() {
return promptTo(new StringBuilder(512), "").toString();
}
public TransferCapability deepCopy() {
TransferCapability newTc = new TransferCapability();
newTc.setCommonName(getCommonName());
newTc.setQueryOptions(EnumSet.copyOf(getQueryOptions()));
newTc.setRole(getRole());
newTc.setStorageOptions(getStorageOptions() == null ? null : getStorageOptions().copy());
newTc.setSopClass(getSopClass());
newTc.setTransferSyntaxes(Arrays.copyOf(getTransferSyntaxes(),getTransferSyntaxes().length));
return newTc;
}
public StringBuilder promptTo(StringBuilder sb, String indent) {
String indent2 = indent + " ";
StringUtils.appendLine(sb, indent, "TransferCapability[cn: ", commonName);
StringUtils.appendLine(sb, indent2, "role: ", role);
sb.append(indent2).append("as: ");
UIDUtils.promptTo(sopClass, sb).append(StringUtils.LINE_SEPARATOR);
for (String ts : transferSyntaxes) {
sb.append(indent2).append("ts: ");
UIDUtils.promptTo(ts, sb).append(StringUtils.LINE_SEPARATOR);
}
if (queryOptions != null)
sb.append(indent2).append("QueryOptions").append(queryOptions)
.append(StringUtils.LINE_SEPARATOR);
if (storageOptions != null)
sb.append(indent2).append(storageOptions)
.append(StringUtils.LINE_SEPARATOR);
return sb.append(indent).append(']');
}
}