Adding registration encounterType, AddressTemplate & AddressHierarchy (#3)

* Adding PATIENT_REGISTRATION encounterType

* Adding address template and address hierarchy to work on 1.10.4

* Testing out the reflection method for installing the address hierarchy

* Returning the POM to 1.10.4
This commit is contained in:
Craig Appl authored and Mark Goodrich committed 2017-04-24 16:04:24 -04:00
1 parent 9e310c516e
commit f8494e8969
14 files changed
+27718 -3

No files matched your search

@@ -14,6 +14,8 @@ import org.apache.commons.logging.LogFactory;
import org.openmrs.api.context.Context;
import org.openmrs.module.BaseModuleActivator;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.HaitiPersonAttributeTypeBundle;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.HaitiEncounterTypeBundle;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.HaitiAddressBundle;
import org.openmrs.module.metadatadeploy.api.MetadataDeployService;
/**
@@ -41,6 +43,8 @@ public class HaitiCoreActivator extends BaseModuleActivator {
private void installMetadataBundles() {
MetadataDeployService deployService = Context.getService(MetadataDeployService.class);
deployService.installBundle(Context.getRegisteredComponents(HaitiPersonAttributeTypeBundle.class).get(0));
deployService.installBundle(Context.getRegisteredComponents(HaitiEncounterTypeBundle.class).get(0));
deployService.installBundle(Context.getRegisteredComponents(HaitiAddressBundle.class).get(0));
}
}
@@ -0,0 +1,180 @@
package org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata;
import org.apache.commons.io.IOUtils;
import org.apache.commons.beanutils.MethodUtils;
import org.openmrs.api.SerializationService;
import org.openmrs.api.context.Context;
import org.openmrs.api.APIException;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.AddressComponent;
import org.openmrs.module.addresshierarchy.AddressHierarchyLevel;
import org.openmrs.module.addresshierarchy.service.AddressHierarchyService;
import org.openmrs.module.addresshierarchy.util.AddressHierarchyImportUtil;
import org.openmrs.module.metadatadeploy.bundle.VersionedMetadataBundle;
import org.openmrs.util.OpenmrsConstants;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class AddressBundle extends VersionedMetadataBundle {
@Autowired
SerializationService serializationService;
/**
* @return the ordered list of address components that make up the address configuration
*/
public abstract List<AddressComponent> getAddressComponents();
/**
* @return the line-by-line format needed by the address template
*/
public abstract List<String> getLineByLineFormat();
/**
* @return the location on the classpath from which to load the address hierarchy entries
*/
public abstract String getAddressHierarchyEntryPath();
@Override
protected void installEveryTime() throws Exception {
installAddressTemplate();
}
@Override
protected void installNewVersion() throws Exception {
AddressHierarchyService service = Context.getService(AddressHierarchyService.class);
// currently we only install the levels if they haven't been installed; no built-in way to edit anything other than "required" at this point
int numberOfLevels = service.getAddressHierarchyLevelsCount();
if (numberOfLevels == 0) {
installAddressHierarchyLevels();
}
else {
updateRequiredProperty();
}
installAddressHierarchyEntries();
}
/**
* Install the appropriate address template
*/
public void installAddressTemplate() throws Exception {
log.info("Installing Address Template");
String template = serializationService.getDefaultSerializer().serialize(getAddressTemplate());
setGlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_ADDRESS_TEMPLATE, template);
}
/**
* @return a new AddressTemplate instance for the given configuration
*/
public Object getAddressTemplate() {
Object addressTemplate = null;
try {
Constructor constructor = Context.loadClass("org.openmrs.layout.web.address.AddressTemplate").getConstructor(String.class);
addressTemplate = constructor.newInstance("");
}
/* Multi-catch exceptions were added to Java 1.7. We need to do a work-around to keep compatibility for 1.6
Ideal Multi-catch would be catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e)
*/
catch (Exception e){
if(e instanceof ClassNotFoundException || e instanceof InstantiationException || e instanceof IllegalAccessException || e instanceof NoSuchMethodException || e instanceof InvocationTargetException) {
try {
Constructor constructor = Context.loadClass("org.openmrs.layout.address.AddressTemplate").getConstructor(String.class);
addressTemplate = constructor.newInstance("");
}
/* Multi-catch exceptions were added to Java 1.7. We need to do a work-around to keep compatibility for 1.6
Ideal Multi-catch would be catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex)
*/
catch (Exception ex){
if(ex instanceof ClassNotFoundException || ex instanceof InstantiationException || ex instanceof IllegalAccessException || ex instanceof NoSuchMethodException || ex instanceof InvocationTargetException) {
throw new APIException("Error while getting address template", ex);
}
}
}
}
Map<String, String> nameMappings = new HashMap<String, String>();
Map<String, String> sizeMappings = new HashMap<String, String>();
Map<String, String> elementDefaults = new HashMap<String, String>();
for (AddressComponent c : getAddressComponents()) {
nameMappings.put(c.getField().getName(), c.getNameMapping());
sizeMappings.put(c.getField().getName(), Integer.toString(c.getSizeMapping()));
if (c.getElementDefault() != null) {
elementDefaults.put(c.getField().getName(), c.getElementDefault());
}
}
try {
MethodUtils.invokeExactMethod(addressTemplate, "setNameMappings", new Object[]{ nameMappings }, new Class[] { Map.class });
MethodUtils.invokeExactMethod(addressTemplate, "setSizeMappings", new Object[]{ sizeMappings }, new Class[] { Map.class });
MethodUtils.invokeExactMethod(addressTemplate, "setElementDefaults", new Object[]{ elementDefaults }, new Class[] { Map.class });
MethodUtils.invokeExactMethod(addressTemplate, "setLineByLineFormat", new Object[]{ getLineByLineFormat() }, new Class[] { List.class });
}
/* Multi-catch exceptions were added to Java 1.7. We need to do a work-around to keep compatibility for 1.6
Ideal Multi-catch would be catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e)
*/
catch (Exception e) {
if (e instanceof NoSuchMethodException || e instanceof IllegalAccessException || e instanceof InvocationTargetException){
throw new APIException("Error while getting address template", e);
}
}
return addressTemplate;
}
/**
* Installed the address hierarchy levels
*/
public void installAddressHierarchyLevels() {
AddressHierarchyService service = Context.getService(AddressHierarchyService.class);
log.info("Installing Address Levels");
AddressHierarchyLevel lastLevel = null;
for (AddressComponent component : getAddressComponents()) {
AddressHierarchyLevel level = new AddressHierarchyLevel();
level.setAddressField(component.getField());
level.setRequired(component.isRequiredInHierarchy());
level.setParent(lastLevel);
service.saveAddressHierarchyLevel(level);
lastLevel = level;
}
}
/**
* Iterate through the levels and update the "required" property in case it has changed
*/
public void updateRequiredProperty() {
AddressHierarchyService service = Context.getService(AddressHierarchyService.class);
log.info("Installing Address Levels");
for (AddressComponent component : getAddressComponents()) {
AddressHierarchyLevel level = service.getAddressHierarchyLevelByAddressField(component.getField());
level.setRequired(component.isRequiredInHierarchy());
service.saveAddressHierarchyLevel(level);
}
}
/**
* Installs a new version of the address hierarchy entries
*/
public void installAddressHierarchyEntries() {
log.info("Installing Address Hierarchy Entries");
Context.getService(AddressHierarchyService.class).deleteAllAddressHierarchyEntries();
InputStream is = null;
try {
is = getClass().getClassLoader().getResourceAsStream(getAddressHierarchyEntryPath());
AddressHierarchyImportUtil.importAddressHierarchyFile(is, "\\|", "\\^");
}
finally {
IOUtils.closeQuietly(is);
}
}
}
@@ -0,0 +1,65 @@
package org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata;
import org.openmrs.module.addresshierarchy.AddressField;
/**
* Represents a component of a hierarchical address
*/
public class AddressComponent {
private AddressField field;
private String nameMapping;
private int sizeMapping;
private String elementDefault;
private boolean requiredInHierarchy;
public AddressComponent() {}
public AddressComponent(AddressField field, String nameMapping, int sizeMapping, String elementDefault, boolean requiredInHierarchy) {
this.field = field;
this.nameMapping = nameMapping;
this.sizeMapping = sizeMapping;
this.elementDefault = elementDefault;
this.requiredInHierarchy = requiredInHierarchy;
}
public AddressField getField() {
return field;
}
public void setField(AddressField field) {
this.field = field;
}
public String getNameMapping() {
return nameMapping;
}
public void setNameMapping(String nameMapping) {
this.nameMapping = nameMapping;
}
public int getSizeMapping() {
return sizeMapping;
}
public void setSizeMapping(int sizeMapping) {
this.sizeMapping = sizeMapping;
}
public String getElementDefault() {
return elementDefault;
}
public void setElementDefault(String elementDefault) {
this.elementDefault = elementDefault;
}
public boolean isRequiredInHierarchy() {
return requiredInHierarchy;
}
public void setRequiredInHierarchy(boolean requiredInHierarchy) {
this.requiredInHierarchy = requiredInHierarchy;
}
}
@@ -0,0 +1,45 @@
package org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata;
import org.openmrs.module.addresshierarchy.AddressField;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.AddressBundle;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.AddressComponent;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class HaitiAddressBundle extends AddressBundle {
@Override
public int getVersion() {
return 9;
}
@Override
public List<AddressComponent> getAddressComponents() {
List<AddressComponent> l = new ArrayList<AddressComponent>();
l.add(new AddressComponent(AddressField.COUNTRY, "haiticore.address.country", 40, "Haiti", true));
l.add(new AddressComponent(AddressField.STATE_PROVINCE, "haiticore.address.stateProvince", 40, null, true));
l.add(new AddressComponent(AddressField.CITY_VILLAGE, "haiticore.address.cityVillage", 40, null, true));
l.add(new AddressComponent(AddressField.ADDRESS_3, "haiticore.address.neighborhoodCell", 60, null, true));
l.add(new AddressComponent(AddressField.ADDRESS_1, "haiticore.address.address1", 60, null, false));
l.add(new AddressComponent(AddressField.ADDRESS_2, "haiticore.address.address2", 60, null, false));
return l;
}
@Override
public List<String> getLineByLineFormat() {
List<String> l = new ArrayList<String>();
l.add("address2");
l.add("address1");
l.add("address3, cityVillage");
l.add("stateProvince, country");
return l;
}
@Override
public String getAddressHierarchyEntryPath() {
return "addresshierarchy/haiti_address_hierarchy_entries_9.csv";
}
}
@@ -0,0 +1,16 @@
package org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata;
import org.openmrs.module.metadatadeploy.bundle.AbstractMetadataBundle;
import org.springframework.stereotype.Component;
@Component
public class HaitiEncounterTypeBundle extends AbstractMetadataBundle {
@Override
public void install() throws Exception {
log.info("Installing EncounterTypes");
install(HaitiEncounterTypes.PATIENT_REGISTRATION);
}
}
@@ -0,0 +1,31 @@
/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata;
import org.openmrs.module.emrapi.EmrApiConstants;
import org.openmrs.module.metadatadeploy.descriptor.EncounterTypeDescriptor;
/**
* Constants for all defined encounter types
*/
public class HaitiEncounterTypes {
public static EncounterTypeDescriptor PATIENT_REGISTRATION = new EncounterTypeDescriptor() {
public String uuid() { return "873f968a-73a8-4f9c-ac78-9f4778b751b6"; }
public String name() { return "Enregistrement de patient"; }
public String description() { return "Patient registration -- normally a new patient"; }
};
}
File diff suppressed because it is too large. Load diff
@@ -3,3 +3,10 @@ openmrs.property.MESSAGE_PROPERTY_ALLOW_KEYS_OUTSIDE_OF_MODULE_NAMESPACE = true
haiticore.title=Haiti Core
ui.i18n.PersonAttributeType.name.14d4f066-15f5-102d-96e4-000c29c2a5d7=Telephone Number
ui.i18n.PersonAttributeType.name.8b56eac7-5c76-4b9c-8c6f-1deab8d3fc47=Unknown patient
haiticore.address.address1 = Locality Habitation
haiticore.address.address2 = Address
haiticore.address.cityVillage = Commune
haiticore.address.country = Country
haiticore.address.neighborhoodCell = Section Communale
haiticore.address.stateProvince = Department
@@ -1,4 +1,11 @@
openmrs.property.MESSAGE_PROPERTY_ALLOW_KEYS_OUTSIDE_OF_MODULE_NAMESPACE = true
ui.i18n.PersonAttributeType.name.14d4f066-15f5-102d-96e4-000c29c2a5d7=Numéro de téléphone
ui.i18n.PersonAttributeType.name.8b56eac7-5c76-4b9c-8c6f-1deab8d3fc47=Patient inconnu
ui.i18n.PersonAttributeType.name.8b56eac7-5c76-4b9c-8c6f-1deab8d3fc47=Patient inconnu
haiticore.address.address1 = Localité Habitation
haiticore.address.address2 = Adresse
haiticore.address.cityVillage = Commune
haiticore.address.country = Pays
haiticore.address.neighborhoodCell = Section communale
haiticore.address.stateProvince = Départment
@@ -2,4 +2,11 @@ openmrs.property.MESSAGE_PROPERTY_ALLOW_KEYS_OUTSIDE_OF_MODULE_NAMESPACE = true
haiticore.title=Haiti Core
ui.i18n.PersonAttributeType.name.14d4f066-15f5-102d-96e4-000c29c2a5d7=Nimewo telefòn
ui.i18n.PersonAttributeType.name.8b56eac7-5c76-4b9c-8c6f-1deab8d3fc47=Pasyan enkoni
ui.i18n.PersonAttributeType.name.8b56eac7-5c76-4b9c-8c6f-1deab8d3fc47=Pasyan enkoni
haiticore.address.address1 = Localitie Habitation
haiticore.address.address2 = Adrès
haiticore.address.cityVillage = Komin
haiticore.address.country = Peyi
haiticore.address.neighborhoodCell = Seksyon kominal
haiticore.address.stateProvince = Départment
@@ -2,16 +2,26 @@ package org.openmrs.module.haiticore;
import org.junit.Test;
import org.openmrs.api.PersonService;
import org.openmrs.api.context.Context;
import org.openmrs.module.addresshierarchy.AddressField;
import org.openmrs.module.addresshierarchy.AddressHierarchyLevel;
import org.openmrs.module.addresshierarchy.service.AddressHierarchyService;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.HaitiPersonAttributeTypeBundle;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.HaitiPersonAttributeTypes;
import org.openmrs.module.haiticore.org.openmrs.module.haiticore.metadata.HaitiAddressBundle;
import org.openmrs.module.metadatadeploy.api.MetadataDeployService;
import org.openmrs.test.BaseModuleContextSensitiveTest;
import org.springframework.beans.factory.annotation.Autowired;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.util.List;
import org.junit.Assert;
public class HaitiCoreActivatorTest extends BaseModuleContextSensitiveTest {
@Autowired
@@ -23,14 +33,50 @@ public class HaitiCoreActivatorTest extends BaseModuleContextSensitiveTest {
@Autowired
private HaitiPersonAttributeTypeBundle personAttributeTypeBundle;
@Autowired
private HaitiAddressBundle addressBundle;
@Test
public void testMetadataBundles() throws Exception {
deployService.installBundle(personAttributeTypeBundle);
deployService.installBundle(addressBundle);
// just test that a few pieces of data exist
assertThat(personService.getAllPersonAttributeTypes().size(), is(7)); // the 4 that the bundle installs + the 3 from standard test dataset
assertNotNull(personService.getPersonAttributeTypeByUuid(HaitiPersonAttributeTypes.MOTHERS_FIRST_NAME.uuid()));
// test the address hierarchy
verifyAddressHierarchyLevelsCreated();
verifyAddressHierarchyLoaded();
}
private void verifyAddressHierarchyLevelsCreated() throws Exception {
AddressHierarchyService ahService = Context.getService(AddressHierarchyService.class);
// assert that we now have six address hierarchy levels
assertEquals(new Integer(6), ahService.getAddressHierarchyLevelsCount());
// make sure they are mapped correctly
List<AddressHierarchyLevel> levels = ahService.getOrderedAddressHierarchyLevels(true);
assertEquals(AddressField.COUNTRY, levels.get(0).getAddressField());
assertEquals(AddressField.STATE_PROVINCE, levels.get(1).getAddressField());
assertEquals(AddressField.CITY_VILLAGE, levels.get(2).getAddressField());
assertEquals(AddressField.ADDRESS_3, levels.get(3).getAddressField());
assertEquals(AddressField.ADDRESS_1, levels.get(4).getAddressField());
assertEquals(AddressField.ADDRESS_2, levels.get(5).getAddressField());
}
private void verifyAddressHierarchyLoaded() throws Exception {
AddressHierarchyService ahService = Context.getService(AddressHierarchyService.class);
// we should now have 26000+ address hierarchy entries
Assert.assertTrue(ahService.getAddressHierarchyEntryCount() > 26000);
assertEquals(2, ahService.getAddressHierarchyEntriesAtTopLevel().size());
assertEquals("Yon lot peyi", ahService.getAddressHierarchyEntriesAtTopLevel().get(0).getName());
assertEquals("Haiti", ahService.getAddressHierarchyEntriesAtTopLevel().get(1).getName());
}
}
@@ -12,6 +12,10 @@
<mapping resource="Provider.hbm.xml"/>
<mapping resource="ProviderRole.hbm.xml"/>
<mapping resource="AddressHierarchyEntry.hbm.xml"/>
<mapping resource="AddressHierarchyLevel.hbm.xml"/>
<mapping resource="AddressToEntryMap.hbm.xml"/>
<mapping resource="MetadataSource.hbm.xml" />
<mapping resource="MetadataTermMapping.hbm.xml" />
+3
View File
@@ -23,6 +23,9 @@
<require_module version="${emrapiVersion}">
org.openmrs.module.emrapi
</require_module>
<require_module version="${addresshierarchyVersion}">
org.openmrs.module.addresshierarchy
</require_module>
</require_modules>
<!-- Internationalization -->
+16 -1
View File
@@ -36,6 +36,7 @@
<properties>
<openMRSVersion>1.10.4</openMRSVersion>
<metadatadeployVersion>1.8.1</metadatadeployVersion>
<addresshierarchyVersion>2.10</addresshierarchyVersion>
<emrapiVersion>1.21.0</emrapiVersion>
<reportingVersion>0.11.0</reportingVersion>
<calculationVersion>1.2</calculationVersion>
@@ -43,7 +44,7 @@
<metadatamappingVersion>1.3.1</metadatamappingVersion>
<metadatasharingVersion>1.2.2</metadatasharingVersion>
<providermanagementVersion>2.5.0</providermanagementVersion>
<jacksonVersion>1.5.0</jacksonVersion>
<jacksonVersion>1.8.3</jacksonVersion>
</properties>
<dependencies>
@@ -57,6 +58,13 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openmrs.web</groupId>
<artifactId>openmrs-web</artifactId>
<version>${openMRSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openmrs.api</groupId>
<artifactId>openmrs-api</artifactId>
@@ -105,6 +113,13 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openmrs.module</groupId>
<artifactId>addresshierarchy-api</artifactId>
<version>${addresshierarchyVersion}</version>
<scope>provided</scope>
</dependency>
<!-- OpenMRS modules required just to fire up application context during testing -->
<dependency>