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.data;
040
041import java.io.Serializable;
042import java.util.ArrayList;
043
044import org.dcm4che3.util.TagUtils;
045
046/**
047 * @author Gunter Zeilinger <gunterze@gmail.com>
048 */
049public class ValueSelector implements Serializable {
050
051    private static final long serialVersionUID = 8346808223314626639L;
052
053    private static final ItemPointer[] NO_ITEMPOINTERS = {};
054    private static final int MIN_ITEM_POINTER_STR_LEN = 43;
055
056    public final int tag;
057    public final String privateCreator;
058    public final VR vr;
059    public final int valueIndex;
060    public final ItemPointer[] itemPointers;
061
062    public ValueSelector(String privateCreator, int tag, VR vr, int index,
063            ItemPointer... itemPointers) {
064        this.tag = tag;
065        this.privateCreator = privateCreator;
066        this.vr = vr;
067        this.valueIndex = index;
068        this.itemPointers = itemPointers.clone();
069    }
070
071    public String selectStringValue(Attributes attrs, String defVal) {
072        Attributes item = attrs.getNestedDataset(itemPointers);
073        return item != null ? item.getString(privateCreator, tag, vr, valueIndex, defVal) : defVal;
074    }
075
076    @Override
077    public String toString() {
078        StringBuilder sb = new StringBuilder(32);
079        for (ItemPointer ip : itemPointers)
080            appendTo(ip.sequenceTag, ip.privateCreator, ip.itemIndex,
081                    "\"]/Item[@number=\"", "\"]/", sb);
082        appendTo(tag, privateCreator, valueIndex,
083                "\"]/Value[@number=\"", "\"]", sb);
084        return sb.toString();
085    }
086
087    private void appendTo(int tag, String privateCreator, int index, String valueOrItem,
088            String suffix, StringBuilder sb) {
089        sb.append("DicomAttribute[@tag=\"").append(TagUtils.toHexString(tag));
090        if (privateCreator != null)
091            sb.append("\" and @privateCreator=\"").append(privateCreator);
092        if (vr != null)
093            sb.append("\" and @vr=\"").append(vr);
094        sb.append(valueOrItem).append(index + 1).append(suffix);
095    }
096
097    public static ValueSelector valueOf(String s) {
098        int fromIndex = s.lastIndexOf("DicomAttribute");
099        try {
100            return new ValueSelector(
101                    selectPrivateCreator(s, fromIndex),
102                    selectTag(s, fromIndex),
103                    selectVR(s, fromIndex),
104                    selectNumber(s, fromIndex) - 1,
105                    itemPointersOf(s, fromIndex));
106        } catch (Exception e) {
107            throw new IllegalArgumentException(s,e);
108        }
109    }
110
111    private static int selectTag(String s, int fromIndex) {
112        String tagStr = select("@tag=", s, fromIndex);
113        return Integer.parseInt(tagStr, 16);
114    }
115
116    private static String selectPrivateCreator(String s, int fromIndex) {
117        return select("@privateCreator=", s, fromIndex);
118    }
119
120    private static int selectNumber(String s, int fromIndex) {
121        String no = select("@number=", s, fromIndex);
122        return Integer.parseInt(no);
123    }
124
125    private static VR selectVR(String s, int fromIndex) {
126        String vrStr = select("@vr=", s, fromIndex);
127        return vrStr != null ? VR.valueOf(vrStr) : null;
128    }
129
130    private static ItemPointer[] itemPointersOf(String s, int endIndex) {
131        if (endIndex == 0)
132            return NO_ITEMPOINTERS;
133
134        ArrayList<ItemPointer> list = new ArrayList<ItemPointer>();
135        int fromIndex = 0;
136        while (fromIndex < endIndex) {
137            list.add(new ItemPointer(
138                    selectPrivateCreator(s, fromIndex),
139                    selectTag(s, fromIndex),
140                    selectNumber(s, fromIndex) - 1));
141            fromIndex = s.indexOf("DicomAttribute",
142                    fromIndex + MIN_ITEM_POINTER_STR_LEN);
143        }
144        return list.toArray(new ItemPointer[list.size()]);
145    }
146
147    private static String select(String key, String s, int fromIndex) {
148        int pos = s.indexOf(key, fromIndex);
149        if (pos < 0)
150            return null;
151        
152        int quotePos = pos + key.length();
153        int beginIndex = quotePos + 1;
154        return s.substring(beginIndex, s.indexOf(s.charAt(quotePos), beginIndex));
155    }
156
157}