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.imageio.codec; 040 041import org.dcm4che3.conf.core.api.ConfigurableClass; 042import org.dcm4che3.conf.core.api.ConfigurableProperty; 043import org.dcm4che3.conf.core.api.LDAP; 044import org.dcm4che3.data.Attributes; 045import org.dcm4che3.data.Tag; 046import org.dcm4che3.image.PhotometricInterpretation; 047 048import java.io.Serializable; 049import java.util.ArrayList; 050import java.util.Collections; 051import java.util.Iterator; 052import java.util.List; 053 054 055/** 056 * @author Gunter Zeilinger <gunterze@gmail.com> 057 * @author Roman K 058 */ 059@ConfigurableClass 060public class CompressionRules 061 implements Iterable<CompressionRule>, Serializable { 062 063 private static final long serialVersionUID = 5027417735779753342L; 064 065 /** 066 * This list has a consistent order wrt config save/load 067 */ 068 @LDAP(noContainerNode = true) 069 @ConfigurableProperty 070 private List<CompressionRule> list = new ArrayList<CompressionRule>(); 071 072 /** 073 * this list is sorted wrt weighting logic (elements with the same weight might not follow a deterministic order) 074 */ 075 private List<CompressionRule> weightedList = new ArrayList<CompressionRule>(); 076 077 public void add(CompressionRule rule) { 078 if (findByCommonName(rule.getCommonName()) != null) 079 throw new IllegalStateException("CompressionRule with cn: '" 080 + rule.getCommonName() + "' already exists"); 081 int index = Collections.binarySearch(weightedList, rule); 082 if (index < 0) 083 index = -(index+1); 084 weightedList.add(index, rule); 085 list.add(rule); 086 } 087 088 public void add(CompressionRules rules) { 089 for (CompressionRule rule : rules) add(rule); 090 } 091 092 /** 093 * Removes a compression rule with the same Common Name 094 * @param ac 095 * @return 096 */ 097 public boolean remove(CompressionRule ac) { 098 099 if (ac == null || ac.getCommonName() == null) 100 return false; 101 102 boolean res = false; 103 Iterator<CompressionRule> iterator = weightedList.iterator(); 104 while (iterator.hasNext()) { 105 CompressionRule compressionRule = iterator.next(); 106 if (ac.getCommonName().equals(compressionRule.getCommonName())) { 107 res = true; 108 // will remove below 109 break; 110 } 111 } 112 113 Iterator<CompressionRule> listIterator = list.iterator(); 114 while (listIterator.hasNext()) { 115 CompressionRule next = listIterator.next(); 116 if (ac.getCommonName().equals(next.getCommonName())) { 117 if (!res) throw new IllegalStateException("Compression rule lists are not consistent, will not remove rule "+next.getCommonName()); 118 listIterator.remove(); 119 iterator.remove(); 120 break; 121 } 122 } 123 return res; 124 } 125 126 public void clear() { 127 weightedList.clear(); 128 list.clear(); 129 } 130 131 public CompressionRule findByCommonName(String commonName) { 132 for (CompressionRule rule : weightedList) 133 if (commonName.equals(rule.getCommonName())) 134 return rule; 135 return null; 136 } 137 138 public CompressionRule findCompressionRule(String aeTitle, Attributes attrs) { 139 try { 140 return findCompressionRule(aeTitle, 141 PhotometricInterpretation.fromString( 142 attrs.getString(Tag.PhotometricInterpretation)), 143 attrs.getInt(Tag.BitsStored, 0), 144 attrs.getInt(Tag.PixelRepresentation, 0), 145 attrs.getString(Tag.SOPClassUID), 146 attrs.getStrings(Tag.ImageType), 147 attrs.getString(Tag.BodyPartExamined)); 148 } catch (IllegalArgumentException ignore) { 149 return null; 150 } 151 } 152 153 public CompressionRule findCompressionRule(String aeTitle, 154 PhotometricInterpretation pmi, 155 int bitsStored, int pixelRepresentation, 156 String sopClass, String[] imgTypes, String bodyPart) { 157 for (CompressionRule ac : weightedList) 158 if (ac.matchesCondition(pmi, bitsStored, pixelRepresentation, 159 aeTitle, sopClass, imgTypes, bodyPart)) 160 return ac; 161 return null; 162 } 163 164 @Override 165 public Iterator<CompressionRule> iterator() { 166 return weightedList.iterator(); 167 } 168 169 public List<CompressionRule> getList() { 170 return list; 171 } 172 173 public void setList(List<CompressionRule> list) { 174 this.list.clear(); 175 this.weightedList.clear(); 176 for (CompressionRule rule : list) add(rule); 177 } 178}