Java tutorial
/** * * Copyright (C) 2002-2012 "SYSNET International, Inc." * support@sysnetint.com [http://www.sysnetint.com] * * This file is part of OpenEMPI. * * OpenEMPI is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.openhie.openempi.configuration; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.PropertyConfigurator; import org.apache.xmlbeans.XmlError; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOptions; import org.openhie.openempi.Constants; import org.openhie.openempi.InitializationException; import org.openhie.openempi.blocking.BlockingService; import org.openhie.openempi.configuration.Component.ComponentType; import org.openhie.openempi.configuration.Component.ExtensionInterface; import org.openhie.openempi.configuration.xml.BlockingConfigurationType; import org.openhie.openempi.configuration.xml.CustomFields; import org.openhie.openempi.configuration.xml.FileLoaderConfigurationType; import org.openhie.openempi.configuration.xml.MatchingConfigurationType; import org.openhie.openempi.configuration.xml.MpiConfigDocument; import org.openhie.openempi.configuration.xml.ScheduledTask; import org.openhie.openempi.configuration.xml.ScheduledTasks; import org.openhie.openempi.configuration.xml.SingleBestRecordType; import org.openhie.openempi.configuration.xml.TransformationFunction; import org.openhie.openempi.configuration.xml.UpdateNotificationEntry; import org.openhie.openempi.configuration.xml.mpicomponent.ExtensionType; import org.openhie.openempi.configuration.xml.mpicomponent.ExtensionType.Interface.Enum; import org.openhie.openempi.configuration.xml.mpicomponent.MpiComponentDefinitionDocument; import org.openhie.openempi.configuration.xml.mpicomponent.MpiComponentType; import org.openhie.openempi.context.Context; import org.openhie.openempi.loader.FileLoaderConfigurationService; import org.openhie.openempi.matching.MatchingService; import org.openhie.openempi.model.IdentifierDomain; import org.openhie.openempi.model.User; import org.openhie.openempi.service.impl.BaseServiceImpl; import org.openhie.openempi.singlebestrecord.SingleBestRecordService; import org.openhie.openempi.util.ConvertUtil; public class Configuration extends BaseServiceImpl implements ConfigurationRegistry { protected static final Log log = LogFactory.getLog(Configuration.class); private String configFile; private MpiConfigDocument configuration; private GlobalIdentifier globalIdentifier; private List<CustomField> customFields; private Map<String, CustomField> customFieldsByName; private AdminConfiguration adminConfiguration; private Map<String, Object> configurationRegistry; private Map<String, Component> extensionRegistry; public void init() { configureLoggingEnvironment(); configurationRegistry = new HashMap<String, Object>(); extensionRegistry = new HashMap<String, Component>(); try { configuration = loadConfigurationFromSource(); validateConfiguration(configuration); processConfiguration(configuration); log.info("System configuration: " + this.toString()); } catch (Exception e) { log.error("Failed while locating and parsing the configuration file. System is shutting down due to: " + e, e); throw new RuntimeException( "Failed while locating and parsing the configuration file. System is shutting down."); } } private void configureLoggingEnvironment() { String openEmpiHome = Context.getOpenEmpiHome(); if (openEmpiHome != null && openEmpiHome.length() > 0) { String loggingConfigurationFile = openEmpiHome + "/conf/log4j.properties"; PropertyConfigurator.configure(loggingConfigurationFile); log.info("Set the logging configuration file to " + loggingConfigurationFile); } } public FileLoaderConfigurationType getFileLoaderConfiguration() { return configuration.getMpiConfig().getFileLoaderConfiguration(); } public FileLoaderConfigurationType saveFileLoaderConfiguration(FileLoaderConfigurationType fileLoaderConfig) { configuration.getMpiConfig().setFileLoaderConfiguration(fileLoaderConfig); return configuration.getMpiConfig().getFileLoaderConfiguration(); } public BlockingConfigurationType getBlockingConfiguration() { return configuration.getMpiConfig().getBlockingConfiguration(); } public BlockingConfigurationType saveBlockingConfiguration(BlockingConfigurationType blocking) { configuration.getMpiConfig().setBlockingConfiguration(blocking); return configuration.getMpiConfig().getBlockingConfiguration(); } private void processConfiguration(MpiConfigDocument configuration) { globalIdentifier = processGlobalIdentifier(configuration); processScheduledTasks(configuration); try { processFileLoaderConfiguration(configuration); } catch (Exception e) { log.warn("Was unable to load the file loader configuration: " + e, e); } customFields = processCustomFields(configuration); try { BlockingService service = processBlockingConfiguration(configuration); if (service == null) { setupNaiveBlockingService(); } } catch (Exception e) { log.error("Was unable to load the blocking configuration: " + e, e); } try { processMatchConfiguration(configuration); } catch (Exception e) { log.warn("Was unable to load the matching service configuration: " + e, e); } try { processSingleBestRecordConfiguration(configuration); } catch (Exception e) { log.warn("Was unable to load the single best record configuration: " + e, e); } adminConfiguration = processAdminConfiguration(configuration); } private List<ScheduledTaskEntry> processScheduledTasks(MpiConfigDocument configuration) { checkConfiguration(configuration); List<ScheduledTaskEntry> list = new ArrayList<ScheduledTaskEntry>(); registerConfigurationEntry(ConfigurationRegistry.SCHEDULED_TASK_LIST, list); ScheduledTasks tasks = configuration.getMpiConfig().getScheduledTasks(); if (tasks == null) { log.warn("No scheduled tasks have been specified in the configuration."); return list; } for (int i = 0; i < tasks.sizeOfScheduledTaskArray(); i++) { org.openhie.openempi.configuration.xml.ScheduledTask taskXml = tasks.getScheduledTaskArray(i); ScheduledTaskEntry entry = buildScheduledTaskFromXml(taskXml); if (entry != null) { list.add(entry); } } return list; } private ScheduledTaskEntry buildScheduledTaskFromXml(ScheduledTask taskXml) { ScheduledTaskEntry taskEntry = new ScheduledTaskEntry(); taskEntry.setTaskName(taskXml.getTaskName()); taskEntry.setTaskImplementation(taskXml.getTaskImplementation()); Object taskImplementation = Context.getApplicationContext().getBean(taskEntry.getTaskImplementation()); if (taskImplementation == null || !(taskImplementation instanceof Runnable)) { log.error( "Encounter an invalid scheduled task entry that will be ignored due to an unknown implementation classs.: " + taskXml); return null; } taskEntry.setRunableTask((Runnable) taskImplementation); taskEntry.setTimeUnit(getTimeUnit(taskXml.getTimeUnit())); if (taskXml.getScheduleType() == null || taskXml.getTimeUnit() == null) { log.error( "Encountered an invalid scheduled task entry that will be ignored due to missing required attributes: " + taskXml); return null; } if (taskXml.getScheduleType().intValue() == ScheduledTask.ScheduleType.SCHEDULE.intValue()) { taskEntry.setDelay(taskXml.getDelay()); taskEntry.setScheduleType(ScheduledTaskEntry.SCHEDULE_ENTRY_TYPE); if (taskEntry.getTaskName() == null || taskEntry.getTaskImplementation() == null || !taskXml.isSetDelay()) { log.error( "Encountered an invalid scheduled task entry that will be ignored due to missing required elements: " + taskXml); return null; } } else if (taskXml.getScheduleType().intValue() == ScheduledTask.ScheduleType.SCHEDULE_AT_FIXED_RATE .intValue()) { taskEntry.setInitialDelay(taskXml.getInitialDelay()); taskEntry.setPeriod(taskXml.getPeriod()); taskEntry.setScheduleType(ScheduledTaskEntry.SCHEDULE_AT_FIXED_RATE_ENTRY_TYPE); if (taskEntry.getTaskName() == null || taskEntry.getTaskImplementation() == null || !taskXml.isSetInitialDelay() || !taskXml.isSetPeriod()) { log.error( "Encountered an invalid scheduled task entry that will be ignored due to missing required parameters.: " + taskXml); return null; } } else if (taskXml.getScheduleType().intValue() == ScheduledTask.ScheduleType.SCHEDULE_WITH_FIXED_DELAY .intValue()) { taskEntry.setDelay(taskXml.getDelay()); taskEntry.setInitialDelay(taskXml.getInitialDelay()); taskEntry.setScheduleType(ScheduledTaskEntry.SCHEDULE_WITH_FIXED_DELAY_ENTRY_TYPE); if (taskEntry.getTaskName() == null || taskEntry.getTaskImplementation() == null || !taskXml.isSetInitialDelay() || !taskXml.isSetDelay()) { log.error( "Encountered an invalid scheduled task entry that will be ignored due to missing required parameters.: " + taskXml); return null; } } return taskEntry; } private TimeUnit getTimeUnit(org.openhie.openempi.configuration.xml.ScheduledTask.TimeUnit.Enum timeUnit) { if (timeUnit == org.openhie.openempi.configuration.xml.ScheduledTask.TimeUnit.DAYS) { return TimeUnit.DAYS; } else if (timeUnit == org.openhie.openempi.configuration.xml.ScheduledTask.TimeUnit.HOURS) { return TimeUnit.HOURS; } else if (timeUnit == org.openhie.openempi.configuration.xml.ScheduledTask.TimeUnit.MICROSECONDS) { return TimeUnit.MICROSECONDS; } else if (timeUnit == org.openhie.openempi.configuration.xml.ScheduledTask.TimeUnit.MILLISECONDS) { return TimeUnit.MILLISECONDS; } else if (timeUnit == org.openhie.openempi.configuration.xml.ScheduledTask.TimeUnit.MINUTES) { return TimeUnit.MINUTES; } else if (timeUnit == org.openhie.openempi.configuration.xml.ScheduledTask.TimeUnit.NANOSECONDS) { return TimeUnit.NANOSECONDS; } else if (timeUnit == org.openhie.openempi.configuration.xml.ScheduledTask.TimeUnit.SECONDS) { return TimeUnit.SECONDS; } log.warn("An unknown time-unit was specified for a scheduled task of " + timeUnit + " so will resort to seconds as the default time unit."); return TimeUnit.SECONDS; } private void setupNaiveBlockingService() { log.warn( "Was unable to load the blocking service configuration; using the naive blocking service as a fallback mechanism."); BlockingService blockingService = (BlockingService) Context.getApplicationContext() .getBean(Constants.NAIVE_BLOCKING_SERVICE); Context.registerCustomBlockingService(blockingService); } private AdminConfiguration processAdminConfiguration(MpiConfigDocument configuration) { adminConfiguration = new AdminConfiguration(); if (configuration.getMpiConfig().getAdminConfiguration() != null) { adminConfiguration.setConfigFileDirectory( configuration.getMpiConfig().getAdminConfiguration().getFileRepositoryDirectory()); } if (adminConfiguration.getConfigFileDirectory() == null) { adminConfiguration.setConfigFileDirectory(Constants.DEFAULT_FILE_REPOSITORY_DIRECTORY); } if (configuration.getMpiConfig().getAdminConfiguration().getUpdateNotificationEntries() != null && configuration.getMpiConfig().getAdminConfiguration().getUpdateNotificationEntries() .sizeOfUpdateNotificationEntryArray() > 0) { UpdateNotificationEntry[] entries = configuration.getMpiConfig().getAdminConfiguration() .getUpdateNotificationEntries().getUpdateNotificationEntryArray(); for (int i = 0; i < entries.length; i++) { UpdateNotificationRegistrationEntry entry = processUpdateNotificationEntry(entries[i]); if (entry != null) { adminConfiguration.addUpdateNotificationRegistrationEntries(entry); } } } return adminConfiguration; } private UpdateNotificationRegistrationEntry processUpdateNotificationEntry(UpdateNotificationEntry xmlEntry) { String userName = xmlEntry.getUser(); if (userName == null || userName.length() == 0) { log.error( "Encountered update notification registration entry without a user account. Entry will be ignored: " + xmlEntry.toString()); return null; } User user = Context.getUserManager().getUserByUsername(userName); if (user == null) { log.error( "Encountered update notification registration entry with an unknown user account. Entry will be ignored: " + xmlEntry.toString()); return null; } String identifierDomainName = xmlEntry.getIdentifierDomainName(); if (identifierDomainName == null || identifierDomainName.length() == 0) { log.error( "Encountered update notification registration entry without an identifier domain. Entry will be ignored: " + xmlEntry.toString()); return null; } IdentifierDomain domain = Context.getPersonQueryService().findIdentifierDomainByName(identifierDomainName); if (domain == null) { log.error( "Encountered update notification registration entry with an unknown domain. Entry will be ignored: " + xmlEntry.toString()); return null; } UpdateNotificationRegistrationEntry entry = new UpdateNotificationRegistrationEntry(user, domain, xmlEntry.getTimeToLive()); log.warn("Adding update notification registration entry: " + entry); return entry; } private GlobalIdentifier processGlobalIdentifier(MpiConfigDocument configuration) { globalIdentifier = new GlobalIdentifier(); if (!configuration.getMpiConfig().isSetGlobalIdentifier()) { globalIdentifier.setAssignGlobalIdentifier(false); return globalIdentifier; } globalIdentifier.setAssignGlobalIdentifier( configuration.getMpiConfig().getGlobalIdentifier().getAssignGlobalIdentifier()); globalIdentifier.setIdentifierDomainName( configuration.getMpiConfig().getGlobalIdentifier().getIdentifierDomainName()); globalIdentifier.setIdentifierDomainDescription( configuration.getMpiConfig().getGlobalIdentifier().getIdentifierDomainDescription()); globalIdentifier.setNamespaceIdentifier( configuration.getMpiConfig().getGlobalIdentifier().getNamespaceIdentifier()); globalIdentifier.setUniversalIdentifier( configuration.getMpiConfig().getGlobalIdentifier().getUniversalIdentifier()); globalIdentifier.setUniversalIdentifierType( configuration.getMpiConfig().getGlobalIdentifier().getUniversalIdentifierType()); IdentifierDomain domain = Context.getPersonQueryService() .findIdentifierDomainByName(globalIdentifier.getIdentifierDomainName()); if (domain == null) { log.error("Global identifier domain not found; correct system configuration and start system again."); System.exit(-1); } globalIdentifier.setIdentifierDomain(domain); return globalIdentifier; } public IdentifierDomain getGlobalIdentifierDomain() { if (globalIdentifier == null) { throw new RuntimeException( "The global identifier configuration has not been specified in the configuration file."); } return globalIdentifier.getIdentifierDomain(); } private BlockingService processBlockingConfiguration(MpiConfigDocument configuration) { checkConfiguration(configuration); BlockingConfigurationType obj = configuration.getMpiConfig().getBlockingConfiguration(); if (obj == null) { log.warn("No blocking service configuration has been specified."); return null; } log.debug("Object is of type: " + obj.getDomNode().getNamespaceURI()); String namespaceUriStr = obj.getDomNode().getNamespaceURI(); URI namespaceURI = getNamespaceURI(namespaceUriStr); String resourcePath = generateComponentResourcePath(namespaceURI); Component component = loadAndRegisterComponentFromNamespaceUri(resourcePath); String configurationLoaderBean = getExtensionBeanNameFromComponent(component); ConfigurationLoader loader = (ConfigurationLoader) Context.getApplicationContext() .getBean(configurationLoaderBean); loader.loadAndRegisterComponentConfiguration(this, obj); Component.Extension extension = component .getExtensionByExtensionInterface(ExtensionInterface.IMPLEMENTATION); if (extension == null) { log.error("Encountered a custom blocking component with no implementation extension: " + component); throw new InitializationException( "Unable to locate an implementation component for custom blocking component " + component.getName()); } log.debug("Registering implementation of blocking component named " + extension.getName() + " and implementation key " + extension.getImplementationKey()); BlockingService blockingService = (BlockingService) Context.getApplicationContext() .getBean(extension.getImplementationKey()); Context.registerCustomBlockingService(blockingService); return blockingService; } private void processSingleBestRecordConfiguration(MpiConfigDocument configuration) { checkConfiguration(configuration); SingleBestRecordType obj = configuration.getMpiConfig().getSingleBestRecord(); if (obj == null) { log.warn("No single best record configuration has been specified."); return; } log.debug("Object is of type: " + obj.getDomNode().getNamespaceURI()); String namespaceUriStr = obj.getDomNode().getNamespaceURI(); URI namespaceURI = getNamespaceURI(namespaceUriStr); String resourcePath = generateComponentResourcePath(namespaceURI); Component component = loadAndRegisterComponentFromNamespaceUri(resourcePath); String configurationLoaderBean = getExtensionBeanNameFromComponent(component); ConfigurationLoader loader = (ConfigurationLoader) Context.getApplicationContext() .getBean(configurationLoaderBean); loader.loadAndRegisterComponentConfiguration(this, obj); Component.Extension extension = component .getExtensionByExtensionInterface(ExtensionInterface.IMPLEMENTATION); if (extension == null) { log.error("Encountered a custom single best record component with no implementation extension: " + component); throw new InitializationException( "Unable to locate an implementation component for custom single best record component " + component.getName()); } log.debug("Registering implementation of single best record component named " + extension.getName() + " and implementation key " + extension.getImplementationKey()); SingleBestRecordService singleBestRecordService = (SingleBestRecordService) Context.getApplicationContext() .getBean(extension.getImplementationKey()); Context.registerCustomSingleBestRecordService(singleBestRecordService); } public MatchingConfigurationType saveMatchingConfiguration(MatchingConfigurationType matchingConfiguration) { configuration.getMpiConfig().setMatchingConfiguration(matchingConfiguration); return configuration.getMpiConfig().getMatchingConfiguration(); } public ConfigurationLoader getBlockingConfigurationLoader() { Component component = lookupExtensionComponentByComponentType(ComponentType.BLOCKING); String loaderBeanName = getExtensionBeanNameFromComponent(component); ConfigurationLoader loader = (ConfigurationLoader) Context.getApplicationContext().getBean(loaderBeanName); return loader; } public ConfigurationLoader getMatchingConfigurationLoader() { Component component = lookupExtensionComponentByComponentType(ComponentType.MATCHING); String loaderBeanName = getExtensionBeanNameFromComponent(component); ConfigurationLoader loader = (ConfigurationLoader) Context.getApplicationContext().getBean(loaderBeanName); return loader; } private void processMatchConfiguration(MpiConfigDocument configuration) { MatchingConfigurationType obj = configuration.getMpiConfig().getMatchingConfiguration(); if (obj == null) { log.warn("No matching service configuration has been specified."); return; } log.debug("Object is of type: " + obj.getDomNode().getNamespaceURI()); String namespaceUriStr = obj.getDomNode().getNamespaceURI(); URI namespaceURI = getNamespaceURI(namespaceUriStr); String resourcePath = generateComponentResourcePath(namespaceURI); Component component = loadAndRegisterComponentFromNamespaceUri(resourcePath); String configurationLoaderBean = getExtensionBeanNameFromComponent(component); ConfigurationLoader loader = (ConfigurationLoader) Context.getApplicationContext() .getBean(configurationLoaderBean); loader.loadAndRegisterComponentConfiguration(this, obj); Component.Extension extension = component .getExtensionByExtensionInterface(ExtensionInterface.IMPLEMENTATION); if (extension == null) { log.error("Encountered a custom matching component with no implementation extension: " + component); throw new InitializationException( "Unable to locate an implementation component for custom matching component " + component.getName()); } log.debug("Registering implementation of matching component named " + extension.getName() + " and implementation key " + extension.getImplementationKey()); MatchingService matchingService = (MatchingService) Context.getApplicationContext() .getBean(extension.getImplementationKey()); Context.registerCustomMatchingService(matchingService); } private void processFileLoaderConfiguration(MpiConfigDocument configuration) { checkConfiguration(configuration); FileLoaderConfigurationType obj = configuration.getMpiConfig().getFileLoaderConfiguration(); if (obj == null) { return; } log.debug("Object is of type: " + obj.getDomNode().getNamespaceURI()); String namespaceUriStr = obj.getDomNode().getNamespaceURI(); URI namespaceURI = getNamespaceURI(namespaceUriStr); String resourcePath = generateComponentResourcePath(namespaceURI); Component component = loadAndRegisterComponentFromNamespaceUri(resourcePath); String configurationLoaderBean = getExtensionBeanNameFromComponent(component); ConfigurationLoader loader = (ConfigurationLoader) Context.getApplicationContext() .getBean(configurationLoaderBean); loader.loadAndRegisterComponentConfiguration(this, obj); Component.Extension extension = component .getExtensionByExtensionInterface(ExtensionInterface.IMPLEMENTATION); if (extension == null) { log.error("Encountered a custom file loader component with no implementation extension: " + component); throw new InitializationException( "Unable to locate an implementation component for custom file loader component " + component.getName()); } log.debug("Registering implementation of file loader component named " + extension.getName() + " and implementation key " + extension.getImplementationKey()); FileLoaderConfigurationService fileLoaderConfigurationService = (FileLoaderConfigurationService) Context .getApplicationContext().getBean(extension.getImplementationKey()); Context.registerCustomFileLoaderConfigurationService(fileLoaderConfigurationService); } public String getExtensionBeanNameFromComponent(Component component) { Component.Extension extension = component .getExtensionByExtensionInterface(ExtensionInterface.CONFIGURATION_LOADER); if (extension == null) { log.error("Encountered a custom component with no configuration loader extension: " + component); throw new InitializationException( "Unable to load configuration for custom component " + component.getName()); } return extension.getImplementationKey(); } public Component lookupExtensionComponentByComponentType(Component.ComponentType type) { if (type == null || type.componentTypeName() == null || type.componentTypeName().length() == 0) { log.warn("Looked up extension component with blank type name: " + type); return null; } log.debug("Looking up extension component of type: " + type.componentTypeName()); return extensionRegistry.get(type.componentTypeName()); } private Component loadAndRegisterComponentFromNamespaceUri(String resourcePath) { Component component; try { InputStream stream = Configuration.class.getResourceAsStream(resourcePath); MpiComponentDefinitionDocument componentDoc = MpiComponentDefinitionDocument.Factory.parse(stream); MpiComponentType componentXml = componentDoc.getMpiComponentDefinition().getMpiComponent(); component = buildComponentFromXml(componentXml); log.debug("Loaded component: " + component); extensionRegistry.put(component.getComponentType().componentTypeName(), component); return component; } catch (IOException e) { log.error("Failed while loading component configuration file: " + resourcePath, e); throw new InitializationException("Failed while loading component configuration file " + resourcePath); } catch (XmlException e) { log.error("Failed while parsing component configuration file: " + resourcePath, e); throw new InitializationException("Failed while parsing component configuration file " + resourcePath); } } private Component buildComponentFromXml(MpiComponentType componentXml) { Component component = new Component(componentXml.getName()); if (componentXml.getDescription() != null) { component.setDescription(componentXml.getDescription()); } if (componentXml.getComponentType().intValue() == MpiComponentType.ComponentType.INT_BLOCKING) { component.setComponentType(ComponentType.BLOCKING); } else if (componentXml.getComponentType().intValue() == MpiComponentType.ComponentType.INT_MATCHING) { component.setComponentType(ComponentType.MATCHING); } else if (componentXml.getComponentType().intValue() == MpiComponentType.ComponentType.INT_FILELOADER) { component.setComponentType(ComponentType.FILELOADER); } log.debug("Component configuration: " + component.getName() + " of type " + component.getComponentType()); for (int i = 0; i < componentXml.getExtensions().sizeOfExtensionArray(); i++) { ExtensionType extension = componentXml.getExtensions().getExtensionArray(i); log.debug("Extension definition is " + extension); component.addExtension(extension.getName(), extension.getImplementation(), getExtensionInterfaceTypeById(extension.getInterface())); } return component; } private ExtensionInterface getExtensionInterfaceTypeById(Enum extensionInterface) { if (extensionInterface.intValue() == ExtensionType.Interface.INT_CONFIGURATION_LOADER) { return ExtensionInterface.CONFIGURATION_LOADER; } else if (extensionInterface.intValue() == ExtensionType.Interface.INT_CONFIGURATION_GUI) { return ExtensionInterface.CONFIGURATION_GUI; } else if (extensionInterface.intValue() == ExtensionType.Interface.INT_IMPLEMENTATION) { return ExtensionInterface.IMPLEMENTATION; } log.error("Unknown extension interface type encountered: " + extensionInterface); throw new RuntimeException("Unknown extension interface type encountered: " + extensionInterface); } private String generateComponentResourcePath(URI namespaceURI) { String resourcePath = "/META-INF" + namespaceURI.getPath() + "-openempi.xml"; // File resourceFile = new File(resourcePath); // if (!resourceFile.exists() || !resourceFile.canRead()) { // log.error("Unable to load component configuration file: " + resourcePath); // throw new RuntimeException("Component configuration file " + resourcePath + " must be readable and present in the classpath"); // } // String baseURI = resourceFile.getParent().replace('\\', '/'); log.debug("Will locate configuration information for namespace from: " + resourcePath); return resourcePath; } private URI getNamespaceURI(String namespaceUriStr) { log.debug("Generating namespace URI for namespace " + namespaceUriStr); try { URI namespaceURI = new URI(namespaceUriStr); return namespaceURI; } catch (URISyntaxException e) { log.error("Failed to construct a namespace URI for namespace " + namespaceUriStr, e); throw new InitializationException( "Unable to parse extended config namespace URI '" + namespaceUriStr + "'.", e); } } /** * TODO Need to implement validation of the custom field names. The convention is that custom fields can range * from custom1 to custom5 but currently there is no code here to check and make sure that the fields specified follow * the convention and there is no duplication (custom1 specified twice for example). * * @param customFieldXml * @return */ private CustomField buildCustomFieldFromXml(org.openhie.openempi.configuration.xml.CustomField customFieldXml) { CustomField customField = new CustomField(); String fieldName = customFieldXml.getFieldName(); customField.setFieldName(fieldName); if (!ConvertUtil.isValidCustomFieldName(fieldName)) { log.error("Not valid custom field name: " + fieldName); throw new InitializationException("Not valid custom field name: " + fieldName); } if (customFieldsByName.containsKey(fieldName)) { log.error("Duplicate custom field name in configuration: " + fieldName); throw new InitializationException("Duplicate custom field name in configuration: " + fieldName); } customField.setSourceFieldName(customFieldXml.getSourceFieldName()); TransformationFunction function = customFieldXml.getTransformationFunction(); customField.setTransformationFunctionName(function.getFunctionName()); if (function.isSetParameters() && function.getParameters().getParameterArray().length > 0) { for (org.openhie.openempi.configuration.xml.Parameter parameter : function.getParameters() .getParameterArray()) { log.debug("Adding parameter (" + parameter.getName() + "," + parameter.getValue() + ") to transformation function " + function.getFunctionName()); customField.addConfigurationParameter(parameter.getName(), parameter.getValue()); } } return customField; } private List<CustomField> processCustomFields(MpiConfigDocument configuration) { checkConfiguration(configuration); customFieldsByName = new HashMap<String, CustomField>(); registerConfigurationEntry(ConfigurationRegistry.CUSTOM_FIELDS_MAP, customFieldsByName); ArrayList<CustomField> list = new ArrayList<CustomField>(); registerConfigurationEntry(ConfigurationRegistry.CUSTOM_FIELDS_LIST, list); CustomFields customFields = configuration.getMpiConfig().getCustomFields(); if (customFields == null) { log.warn("No custom fields have been specified in the configuration."); return list; } for (int i = 0; i < customFields.sizeOfCustomFieldArray(); i++) { org.openhie.openempi.configuration.xml.CustomField customFieldXml = customFields.getCustomFieldArray(i); CustomField customField = buildCustomFieldFromXml(customFieldXml); if (customField != null) { customFieldsByName.put(customField.getFieldName(), customField); list.add(customField); } } return list; } public void saveAndRegisterCustomFieldsConfiguration(List<CustomField> customFieldsConfiguration) { customFields = customFieldsConfiguration; customFieldsByName.clear(); for (CustomField customField : customFields) { customFieldsByName.put(customField.getFieldName(), customField); } org.openhie.openempi.configuration.xml.CustomFields customFieldsType = buildCustomFieldsFragment( customFields); log.debug("Built custom-field segment: " + customFieldsType.toString()); configuration.getMpiConfig().setCustomFields(customFieldsType); saveConfiguration(); registerConfigurationEntry(ConfigurationRegistry.CUSTOM_FIELDS_MAP, customFieldsByName); registerConfigurationEntry(ConfigurationRegistry.CUSTOM_FIELDS_LIST, customFields); } private org.openhie.openempi.configuration.xml.CustomFields buildCustomFieldsFragment( List<CustomField> customFieldsConfiguration) { org.openhie.openempi.configuration.xml.CustomFields customFieldsType = org.openhie.openempi.configuration.xml.CustomFields.Factory .newInstance(); for (CustomField customField : customFieldsConfiguration) { org.openhie.openempi.configuration.xml.CustomField customFieldXml = customFieldsType .addNewCustomField(); customFieldXml.setFieldName(customField.getFieldName()); customFieldXml.setSourceFieldName(customField.getSourceFieldName()); TransformationFunction function = customFieldXml.addNewTransformationFunction(); function.setFunctionName(customField.getTransformationFunctionName()); if (customField.hasConfigurationParameters()) { org.openhie.openempi.configuration.xml.Parameters params = function.addNewParameters(); for (String paramName : customField.getConfigurationParameters().keySet()) { org.openhie.openempi.configuration.xml.Parameter param = params.addNewParameter(); param.setName(paramName); param.setValue(customField.getConfigurationParameters().get(paramName)); } } } return customFieldsType; } private void checkConfiguration(MpiConfigDocument configuration) { if (configuration == null) { log.error("The configuration of the system has not been initialized."); throw new RuntimeException("The configuration of the system has not been properly initialized."); } } private void validateConfiguration(MpiConfigDocument configuration) { // Set up the validation error listener. ArrayList<XmlError> validationErrors = new ArrayList<XmlError>(); XmlOptions validationOptions = new XmlOptions(); validationOptions.setErrorListener(validationErrors); // During validation, errors are added to the ArrayList for // retrieval and printing by the printErrors method. boolean isValid = configuration.validate(validationOptions); // Print the errors if the XML is invalid. if (!isValid) { java.util.Iterator<XmlError> iter = validationErrors.iterator(); StringBuffer sb = new StringBuffer("MPI Configuration validation errors:\n"); while (iter.hasNext()) { sb.append(">> ").append(iter.next()).append("\n"); } } } private MpiConfigDocument loadConfigurationFromSource() throws XmlException, IOException { File file = getDefaultConfigurationFile(); log.debug("Checking for presence of the configuration in file: " + file.getAbsolutePath()); if (file.exists() && file.isFile()) { log.info("Loading configuration from file: " + file.getAbsolutePath()); return MpiConfigDocument.Factory.parse(file); } URL fileUrl = Configuration.class.getResource(configFile); if (fileUrl != null) { log.info("Loading configuration from URL: " + fileUrl); return MpiConfigDocument.Factory.parse(fileUrl); } log.error("Unable to load configuration information."); throw new RuntimeException("Unable to load configuration information."); } public void saveConfiguration() { File file = getDefaultConfigurationFile(); log.debug("Storing current configuration in file: " + file.getAbsolutePath()); try { XmlOptions opts = new XmlOptions(); opts.setSavePrettyPrint(); opts.setSavePrettyPrintIndent(4); configuration.save(file, opts); } catch (IOException e) { log.error("Unable to save the updated configuration in file: " + file.getAbsolutePath()); throw new RuntimeException("Unable to save the updated configuration: " + e.getMessage()); } } private File getDefaultConfigurationFile() { File dir = new File(Context.getOpenEmpiHome() + "/conf"); System.out.println(System.getProperty("OPENEMPI_HOME")); File file = new File(dir, getConfigurationFilename()); return file; } private String getConfigurationFilename() { String filename = System.getProperty(Constants.OPENEMPI_CONFIGURATION_FILENAME); if (filename != null) { return filename; } return configFile; } public Object lookupConfigurationEntry(String key) { log.debug("Looking up configuration entry with key " + key); return configurationRegistry.get(key); } public void registerConfigurationEntry(String key, Object entry) { log.debug("Registering configuration entry " + entry + " with key " + key); configurationRegistry.put(key, entry); } public String getConfigFile() { return configFile; } public void setConfigFile(String configFile) { this.configFile = configFile; } public List<CustomField> getCustomFields() { return customFields; } public void setCustomFields(List<CustomField> customFields) { this.customFields = customFields; } public AdminConfiguration getAdminConfiguration() { return adminConfiguration; } public void setAdminConfiguration(AdminConfiguration adminConfiguration) { this.adminConfiguration = adminConfiguration; } public GlobalIdentifier getGlobalIdentifier() { return globalIdentifier; } @Override public String toString() { return new ToStringBuilder(this).append("customFields", customFields).toString(); } }