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}