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.service; 040 041import org.dcm4che3.data.Tag; 042import org.dcm4che3.data.Attributes; 043import org.dcm4che3.data.IOD; 044import org.dcm4che3.data.VR; 045import org.dcm4che3.data.ValidationResult; 046import org.dcm4che3.net.Status; 047 048public enum QueryRetrieveLevel { 049 PATIENT, 050 STUDY, 051 SERIES, 052 IMAGE, 053 FRAME { 054 @Override 055 protected IOD queryKeysIOD(QueryRetrieveLevel rootLevel, 056 boolean relational) { 057 throw new UnsupportedOperationException(); 058 } 059 060 @Override 061 protected IOD retrieveKeysIOD(QueryRetrieveLevel rootLevel, 062 boolean relational) { 063 return IMAGE.retrieveKeysIOD(rootLevel, relational); 064 } 065 }; 066 067 private static final int[] UNIQUE_KEYS = { 068 Tag.PatientID, 069 Tag.StudyInstanceUID, 070 Tag.SeriesInstanceUID, 071 Tag.SOPInstanceUID 072 }; 073 074 private static final VR[] UNIQUE_KEYS_VR = { VR.LO, VR.UI, VR.UI, VR.UI }; 075 private static final int[] UNIQUE_KEYS_VM = { 1, -1, -1, -1 }; 076 077 public static QueryRetrieveLevel valueOf(Attributes attrs, 078 String[] qrLevels) throws DicomServiceException { 079 ValidationResult result = new ValidationResult(); 080 attrs.validate(new IOD.DataElement(Tag.QueryRetrieveLevel, VR.LO, 081 IOD.DataElementType.TYPE_1, 1, 1, 0).setValues(qrLevels), 082 result); 083 check(result); 084 return QueryRetrieveLevel.valueOf(attrs.getString(Tag.QueryRetrieveLevel)); 085 } 086 087 public void validateQueryKeys(Attributes attrs, 088 QueryRetrieveLevel rootLevel, boolean relational) 089 throws DicomServiceException { 090 check(attrs.validate(queryKeysIOD(rootLevel, relational))); 091 } 092 093 public void validateRetrieveKeys(Attributes attrs, 094 QueryRetrieveLevel rootLevel, boolean relational) 095 throws DicomServiceException { 096 check(attrs.validate(retrieveKeysIOD(rootLevel, relational))); 097 } 098 099 protected IOD queryKeysIOD(QueryRetrieveLevel rootLevel, boolean relational) { 100 if (compareTo(rootLevel) < 0) 101 throw new IllegalArgumentException("rootLevel:" + rootLevel); 102 103 IOD iod = new IOD(); 104 for (int i = 0; i < rootLevel.ordinal(); i++) { 105 iod.add(new IOD.DataElement(UNIQUE_KEYS[i], UNIQUE_KEYS_VR[i], 106 IOD.DataElementType.TYPE_3, 1, 1, 0)); 107 } 108 int ordinal = ordinal(); 109 IOD.DataElementType type = relational ? IOD.DataElementType.TYPE_3 : IOD.DataElementType.TYPE_1; 110 for (int i = rootLevel.ordinal(); i < ordinal; i++) { 111 iod.add(new IOD.DataElement(UNIQUE_KEYS[i], UNIQUE_KEYS_VR[i], type, 1, 1, 0)); 112 } 113 for (int i = ordinal + 1; i < UNIQUE_KEYS.length; i++) { 114 iod.add(new IOD.DataElement(UNIQUE_KEYS[i], VR.UI, IOD.DataElementType.TYPE_0, -1, -1, 0)); 115 } 116 return iod; 117 } 118 119 protected IOD retrieveKeysIOD(QueryRetrieveLevel rootLevel, boolean relational) { 120 if (compareTo(rootLevel) < 0) 121 throw new IllegalArgumentException("rootLevel:" + rootLevel); 122 123 IOD iod = new IOD(); 124 for (int i = 0; i < rootLevel.ordinal(); i++) { 125 iod.add(new IOD.DataElement(UNIQUE_KEYS[i], UNIQUE_KEYS_VR[i], 126 IOD.DataElementType.TYPE_0, -1, -1, 0)); 127 } 128 int ordinal = ordinal(); 129 IOD.DataElementType type = relational ? IOD.DataElementType.TYPE_3 : IOD.DataElementType.TYPE_1; 130 for (int i = rootLevel.ordinal(); i < ordinal; i++) { 131 iod.add(new IOD.DataElement(UNIQUE_KEYS[i], UNIQUE_KEYS_VR[i], type, 1, 1, 0)); 132 } 133 iod.add(new IOD.DataElement(UNIQUE_KEYS[ordinal], UNIQUE_KEYS_VR[ordinal], 134 IOD.DataElementType.TYPE_1, UNIQUE_KEYS_VM[ordinal], UNIQUE_KEYS_VM[ordinal], 0)); 135 for (int i = ordinal + 1; i < UNIQUE_KEYS.length; i++) { 136 iod.add(new IOD.DataElement(UNIQUE_KEYS[i], VR.UI, IOD.DataElementType.TYPE_0, -1, -1, 0)); 137 } 138 return iod; 139 } 140 141 private static void check(ValidationResult result) throws DicomServiceException { 142 if (!result.isValid()) 143 throw new DicomServiceException( 144 Status.IdentifierDoesNotMatchSOPClass, 145 result.getErrorComment()) 146 .setOffendingElements(result.getOffendingElements()); 147 } 148}