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.IOException; 042import java.util.ArrayList; 043import java.util.Collection; 044import java.util.ListIterator; 045 046import org.dcm4che3.io.DicomEncodingOptions; 047import org.dcm4che3.io.DicomOutputStream; 048 049 050/** 051 * @author Gunter Zeilinger <gunterze@gmail.com> 052 */ 053public class Sequence extends ArrayList<Attributes> implements Value { 054 055 private static final long serialVersionUID = 7062970085409148066L; 056 057 private final Attributes parent; 058 private final String privateCreator; 059 private final int tag; 060 private int length = -1; 061 062 Sequence(Attributes parent, String privateCreator, int tag, int initialCapacity) { 063 super(initialCapacity); 064 this.parent = parent; 065 this.privateCreator = privateCreator; 066 this.tag = tag; 067 } 068 069 public final Attributes getParent() { 070 return parent; 071 } 072 073 public void trimToSize(boolean recursive) { 074 super.trimToSize(); 075 if (recursive) 076 for (Attributes attrs: this) 077 attrs.trimToSize(recursive); 078 } 079 080 @Override 081 public int indexOf(Object o) { 082 ListIterator<Attributes> it = listIterator(); 083 while (it.hasNext()) 084 if (it.next() == o) 085 return it.previousIndex(); 086 return -1; 087 } 088 089 @Override 090 public boolean add(Attributes attrs) { 091 return super.add(attrs.setParent(parent, privateCreator, tag)); 092 } 093 094 @Override 095 public void add(int index, Attributes attrs) { 096 super.add(index, attrs.setParent(parent, privateCreator, tag)); 097 } 098 099 @Override 100 public boolean addAll(Collection<? extends Attributes> c) { 101 setParent(c); 102 return super.addAll(c); 103 } 104 105 private void setParent(Collection<? extends Attributes> c) { 106 boolean bigEndian = parent.bigEndian(); 107 for (Attributes attrs : c) { 108 if (attrs.bigEndian() != bigEndian) 109 throw new IllegalArgumentException( 110 "Endian of Item must match Endian of parent Data Set"); 111 if (!attrs.isRoot()) 112 throw new IllegalArgumentException( 113 "Item already contained by Sequence"); 114 } 115 for (Attributes attrs : c) 116 attrs.setParent(parent, privateCreator, tag); 117 } 118 119 @Override 120 public boolean addAll(int index, Collection<? extends Attributes> c) { 121 setParent(c); 122 return super.addAll(index, c); 123 } 124 125 @Override 126 public void clear() { 127 for (Attributes attrs: this) 128 attrs.setParent(null, null, 0); 129 super.clear(); 130 } 131 132 @Override 133 public Attributes remove(int index) { 134 return super.remove(index).setParent(null, null, 0); 135 } 136 137 @Override 138 public boolean remove(Object o) { 139 if (o instanceof Attributes && super.remove(o)) { 140 ((Attributes) o).setParent(null, null, 0); 141 return true; 142 } 143 return false; 144 } 145 146 @Override 147 public Attributes set(int index, Attributes attrs) { 148 return super.set(index, attrs.setParent(parent, privateCreator, tag)); 149 } 150 151 @Override 152 public String toString() { 153 return "" + size() + " Items"; 154 } 155 156 @Override 157 public int calcLength(DicomEncodingOptions encOpts, boolean explicitVR, VR vr) { 158 int len = 0; 159 for (Attributes item : this) { 160 len += 8 + item.calcLength(encOpts, explicitVR); 161 if (item.isEmpty() ? encOpts.undefEmptyItemLength 162 : encOpts.undefItemLength) 163 len += 8; 164 } 165 if (isEmpty() ? encOpts.undefEmptySequenceLength 166 : encOpts.undefSequenceLength) 167 len += 8; 168 length = len; 169 return len; 170 } 171 172 @Override 173 public int getEncodedLength(DicomEncodingOptions encOpts, boolean explicitVR, VR vr) { 174 if (isEmpty()) 175 return encOpts.undefEmptySequenceLength ? -1 : 0; 176 177 if (encOpts.undefSequenceLength) 178 return -1; 179 180 if (length == -1) 181 calcLength(encOpts, explicitVR, vr); 182 183 return length; 184 } 185 186 @Override 187 public void writeTo(DicomOutputStream out, VR vr) throws IOException { 188 for (Attributes item : this) 189 item.writeItemTo(out); 190 } 191 192 @Override 193 public byte[] toBytes(VR vr, boolean bigEndian) throws IOException { 194 throw new UnsupportedOperationException(); 195 } 196}