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-2014 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.conf.dicom; 040 041import org.dcm4che3.conf.ConfigurationSettingsLoader; 042import org.dcm4che3.conf.core.DefaultBeanVitalizer; 043import org.dcm4che3.conf.core.ExtensionMergingConfiguration; 044import org.dcm4che3.conf.core.api.Configuration; 045import org.dcm4che3.conf.core.api.ConfigurationException; 046import org.dcm4che3.conf.core.api.Path; 047import org.dcm4che3.conf.core.index.ReferenceIndexingDecorator; 048import org.dcm4che3.conf.core.normalization.DefaultsAndNullFilterDecorator; 049import org.dcm4che3.conf.core.olock.HashBasedOptimisticLockingConfiguration; 050import org.dcm4che3.conf.core.storage.SimpleCachingConfigurationDecorator; 051import org.dcm4che3.conf.core.storage.SingleJsonFileConfigurationStorage; 052import org.dcm4che3.net.AEExtension; 053import org.dcm4che3.net.DeviceExtension; 054import org.dcm4che3.net.hl7.HL7ApplicationExtension; 055import org.slf4j.Logger; 056import org.slf4j.LoggerFactory; 057 058import java.util.*; 059 060/** 061 * @author Gunter Zeilinger <gunterze@gmail.com> 062 */ 063public class DicomConfigurationBuilder { 064 065 private Hashtable<?, ?> props; 066 067 private static Logger LOG = LoggerFactory 068 .getLogger(DicomConfigurationBuilder.class); 069 070 private boolean extensionMerge = false; 071 private boolean cache = false; 072 private Hashtable<?, ?> ldapProps = null; 073 private Configuration configurationStorage = null; 074 private Map<Class, List<Class>> extensionClassesMap = new HashMap<Class, List<Class>>(); 075 private boolean doOptimisticLocking = false; 076 private boolean uuidIndexing = true; 077 078 private void setLdapProps(Hashtable<?, ?> ldapProps) { 079 this.ldapProps = ldapProps; 080 } 081 082 public DicomConfigurationBuilder() { 083 this.props = new Hashtable<Object, Object>(); 084 } 085 086 public DicomConfigurationBuilder(Hashtable<?, ?> props) { 087 this.props = props; 088 } 089 090 public DicomConfigurationBuilder registerCustomConfigurationStorage(Configuration storage) { 091 configurationStorage = storage; 092 return this; 093 } 094 095 096 public DicomConfigurationBuilder registerExtensionForBaseExtension(Class extensionClass, Class baseExtensionClass) { 097 098 List<Class> extensionClasses = extensionClassesMap.get(baseExtensionClass); 099 100 if (extensionClasses == null) { 101 extensionClasses = new ArrayList<Class>(); 102 extensionClassesMap.put(baseExtensionClass, extensionClasses); 103 } 104 105 // don't put duplicates 106 if (!extensionClasses.contains(extensionClass)) 107 extensionClasses.add(extensionClass); 108 109 return this; 110 } 111 112 public <T extends DeviceExtension> DicomConfigurationBuilder registerDeviceExtension( 113 Class<T> clazz) { 114 registerExtensionForBaseExtension(clazz, DeviceExtension.class); 115 return this; 116 } 117 118 public <T extends AEExtension> DicomConfigurationBuilder registerAEExtension( 119 Class<T> clazz) { 120 registerExtensionForBaseExtension(clazz, AEExtension.class); 121 return this; 122 } 123 124 public <T extends HL7ApplicationExtension> DicomConfigurationBuilder registerHL7ApplicationExtension( 125 Class<T> clazz) { 126 registerExtensionForBaseExtension(clazz, HL7ApplicationExtension.class); 127 return this; 128 } 129 130 public DicomConfigurationBuilder extensionMerge(boolean extensionMerge) { 131 this.extensionMerge = extensionMerge; 132 return this; 133 } 134 135 public DicomConfigurationBuilder cache(boolean cache) { 136 this.cache = cache; 137 return this; 138 } 139 140 141 public DicomConfigurationBuilder uuidIndexing() { 142 this.uuidIndexing = true; 143 return this; 144 } 145 146 public DicomConfigurationBuilder disableUuidIndexing() { 147 this.uuidIndexing = false; 148 return this; 149 } 150 151 public CommonDicomConfigurationWithHL7 build() throws ConfigurationException { 152 153 List<Class> allExtensions = new ArrayList<Class>(); 154 155 for (Map.Entry<Class, List<Class>> classListEntry : extensionClassesMap.entrySet()) 156 allExtensions.addAll(classListEntry.getValue()); 157 158 Configuration configurationStorage = createConfigurationStorage(allExtensions); 159 if (configurationStorage == null) return null; 160 161 162 for (Map.Entry<Class, List<Class>> classListEntry : extensionClassesMap.entrySet()) 163 LOG.info("Dcm4che configuration {} classes: {}", classListEntry.getKey().getSimpleName(), classListEntry.getValue()); 164 165 166 // check if we have any extensions that have equal simple name and fail if found 167 HashSet<String> simpleNames = new HashSet<String>(); 168 for (Class extension : allExtensions) { 169 if (!simpleNames.add(extension.getSimpleName())) 170 171 throw new ConfigurationException( 172 "Duplicate configuration class extension name '" 173 + extension.getSimpleName() 174 + "'. Make sure that simple class names of extensions are unique!"); 175 } 176 177 178 return new CommonDicomConfigurationWithHL7(configurationStorage, extensionClassesMap); 179 } 180 181 protected Configuration createConfigurationStorage(List<Class> allExtensions) throws ConfigurationException { 182 183 // if configurationStorage is already set - skip the storage init 184 if (configurationStorage == null) { 185 String configType = ConfigurationSettingsLoader.getPropertyWithNotice(props, 186 Configuration.CONF_STORAGE_SYSTEM_PROP, "json_file", 187 " Possible values: 'json_file'."); 188 189 switch (Configuration.ConfigStorageType.valueOf(configType.toUpperCase().trim())) { 190 case JSON_FILE: 191 SingleJsonFileConfigurationStorage jsonConfigurationStorage = createJsonFileConfigurationStorage(); 192 jsonConfigurationStorage.configure(props); 193 configurationStorage = jsonConfigurationStorage; 194 break; 195 default: 196 throw new RuntimeException("Not implemented"); 197 } 198 } 199 200 if (cache) 201 configurationStorage = new SimpleCachingConfigurationDecorator(configurationStorage, props); 202 203 if(extensionMerge) 204 configurationStorage = new ExtensionMergingConfiguration(configurationStorage, allExtensions); 205 206 if (uuidIndexing) 207 configurationStorage = new ReferenceIndexingDecorator(configurationStorage, new HashMap<String, Path>()); 208 209 if (doOptimisticLocking) 210 configurationStorage = new HashBasedOptimisticLockingConfiguration(configurationStorage, allExtensions); 211 212 configurationStorage = new DefaultsAndNullFilterDecorator( 213 configurationStorage, 214 allExtensions, 215 CommonDicomConfiguration.createDefaultDicomVitalizer() 216 ); 217 218 return configurationStorage; 219 } 220 221 protected SingleJsonFileConfigurationStorage createJsonFileConfigurationStorage() { 222 return new SingleJsonFileConfigurationStorage(); 223 } 224 225 public static DicomConfigurationBuilder newConfigurationBuilder(Hashtable<?, ?> props) 226 throws ConfigurationException { 227 return new DicomConfigurationBuilder(props); 228 } 229 230 public static DicomConfigurationBuilder newJsonConfigurationBuilder(String fileName) { 231 Hashtable<Object, Object> props = new Hashtable<Object, Object>(); 232 props.put("org.dcm4che.conf.storage", "json_file"); 233 props.put("org.dcm4che.conf.filename", fileName); 234 return new DicomConfigurationBuilder(props); 235 } 236 237 @Deprecated 238 public static DicomConfigurationBuilder newLdapConfigurationBuilder(Hashtable<?, ?> ldapProps) 239 throws ConfigurationException { 240 Hashtable<Object, Object> props = new Hashtable<Object, Object>(); 241 props.put("org.dcm4che.conf.storage", "ldap"); 242 DicomConfigurationBuilder dicomConfigurationBuilder = new DicomConfigurationBuilder(props); 243 dicomConfigurationBuilder.setLdapProps(ldapProps); 244 return dicomConfigurationBuilder; 245 } 246 247 public DicomConfigurationBuilder optimisticLocking(boolean doOptimisticLocking) { 248 this.doOptimisticLocking = doOptimisticLocking; 249 return this; 250 } 251}