Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit cee79d1

Browse files
committed
Restrict disease values to active ones only
1 parent 13788ea commit cee79d1

4 files changed

Lines changed: 66 additions & 84 deletions

File tree

sormas-api/src/main/java/de/symeda/sormas/api/importexport/ImportColumn.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ private static String computeCaption(String entityName, String columnName) {
101101
}
102102

103103
/**
104-
* Computes the data type accepted for a certain field type. For values which cannot be determined at start a placeholder will be used (ex: <code>${activeDiseases}</code>.
104+
* Computes the data type accepted for a certain field type. For values which cannot be determined at start a placeholder will be used (ex: {@link ImportFacade#ACTIVE_DISEASES_PLACEHOLDER}).
105105
*
106106
* @param fieldType type of a CSV field (column)
107107
* @return a data type description, example or placeholder
@@ -114,7 +114,7 @@ private static String computeDataType(Class<?> fieldType) {
114114
} else if (ReferenceDto.class.isAssignableFrom(fieldType)) {
115115
return String.format(I18nProperties.getString(Strings.nameOf), DataHelper.getHumanClassName(fieldType));
116116
} else if (Disease.class.isAssignableFrom(fieldType)) {
117-
return "${activeDiseases}";
117+
return ImportFacade.ACTIVE_DISEASES_PLACEHOLDER;
118118
} else if (fieldType.isEnum()) {
119119
List<String> enumNames = new ArrayList<>();
120120
for (Object enumConstant : fieldType.getEnumConstants()) {

sormas-api/src/main/java/de/symeda/sormas/api/importexport/ImportFacade.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
@Remote
2525
public interface ImportFacade {
2626

27+
String ACTIVE_DISEASES_PLACEHOLDER = "${activeDiseases}";
28+
2729
/**
2830
* Creates a .csv file with one row containing all relevant column names of the case entity
2931
* and its sub-entities and returns the path to the .csv file that can then be used to offer
@@ -72,4 +74,6 @@ public interface ImportFacade {
7274
String getCaseContactImportTemplateFilePath();
7375

7476
String getContactImportTemplateFilePath();
77+
78+
String getImportTemplateContent(String templateFilePath) throws IOException;
7579
}

sormas-backend/src/main/java/de/symeda/sormas/backend/importexport/ImportFacadeEjb.java

Lines changed: 40 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,24 @@
2222
import java.lang.reflect.Field;
2323
import java.lang.reflect.Method;
2424
import java.lang.reflect.Modifier;
25+
import java.nio.charset.Charset;
26+
import java.nio.charset.StandardCharsets;
2527
import java.nio.file.Files;
2628
import java.nio.file.Path;
2729
import java.nio.file.Paths;
2830
import java.util.ArrayList;
2931
import java.util.Arrays;
3032
import java.util.Collection;
3133
import java.util.Date;
34+
import java.util.HashMap;
3235
import java.util.List;
36+
import java.util.Map;
3337
import java.util.stream.Collectors;
3438

3539
import javax.ejb.EJB;
3640
import javax.ejb.LocalBean;
3741
import javax.ejb.Stateless;
38-
import javax.persistence.EntityManager;
39-
import javax.persistence.PersistenceContext;
42+
import javax.inject.Provider;
4043

4144
import de.symeda.sormas.api.Disease;
4245
import de.symeda.sormas.api.caze.CaseOrigin;
@@ -48,6 +51,7 @@
4851
import de.symeda.sormas.api.importexport.ImportColumn;
4952
import de.symeda.sormas.api.person.Sex;
5053
import de.symeda.sormas.api.utils.CSVCommentLineValidator;
54+
import org.apache.commons.lang3.StringUtils;
5155
import org.slf4j.Logger;
5256
import org.slf4j.LoggerFactory;
5357

@@ -82,70 +86,20 @@
8286
import de.symeda.sormas.api.user.UserReferenceDto;
8387
import de.symeda.sormas.api.utils.CSVUtils;
8488
import de.symeda.sormas.api.utils.DependingOnFeatureType;
85-
import de.symeda.sormas.backend.caze.CaseFacadeEjb.CaseFacadeEjbLocal;
86-
import de.symeda.sormas.backend.caze.CaseService;
8789
import de.symeda.sormas.backend.common.ConfigFacadeEjb.ConfigFacadeEjbLocal;
88-
import de.symeda.sormas.backend.epidata.EpiDataService;
89-
import de.symeda.sormas.backend.facility.FacilityFacadeEjb.FacilityFacadeEjbLocal;
90-
import de.symeda.sormas.backend.facility.FacilityService;
9190
import de.symeda.sormas.backend.feature.FeatureConfigurationFacadeEjb.FeatureConfigurationFacadeEjbLocal;
92-
import de.symeda.sormas.backend.hospitalization.HospitalizationService;
93-
import de.symeda.sormas.backend.person.PersonFacadeEjb.PersonFacadeEjbLocal;
94-
import de.symeda.sormas.backend.person.PersonService;
95-
import de.symeda.sormas.backend.region.CommunityFacadeEjb.CommunityFacadeEjbLocal;
96-
import de.symeda.sormas.backend.region.CommunityService;
97-
import de.symeda.sormas.backend.region.DistrictFacadeEjb.DistrictFacadeEjbLocal;
98-
import de.symeda.sormas.backend.region.DistrictService;
99-
import de.symeda.sormas.backend.region.RegionFacadeEjb.RegionFacadeEjbLocal;
100-
import de.symeda.sormas.backend.region.RegionService;
101-
import de.symeda.sormas.backend.user.UserFacadeEjb.UserFacadeEjbLocal;
102-
import de.symeda.sormas.backend.user.UserService;
103-
import de.symeda.sormas.backend.util.ModelConstants;
10491

10592
@Stateless(name = "ImportFacade")
10693
public class ImportFacadeEjb implements ImportFacade {
10794

10895
private final Logger logger = LoggerFactory.getLogger(getClass());
10996

110-
@PersistenceContext(unitName = ModelConstants.PERSISTENCE_UNIT_NAME)
111-
private EntityManager em;
112-
11397
@EJB
11498
private ConfigFacadeEjbLocal configFacade;
11599
@EJB
116-
private CaseFacadeEjbLocal caseFacade;
117-
@EJB
118-
private CaseService caseService;
119-
@EJB
120-
private UserService userService;
121-
@EJB
122-
private UserFacadeEjbLocal userFacade;
123-
@EJB
124-
private RegionService regionService;
125-
@EJB
126-
private RegionFacadeEjbLocal regionFacade;
127-
@EJB
128-
private DistrictService districtService;
129-
@EJB
130-
private DistrictFacadeEjbLocal districtFacade;
131-
@EJB
132-
private CommunityService communityService;
133-
@EJB
134-
private CommunityFacadeEjbLocal communityFacade;
135-
@EJB
136-
private FacilityService facilityService;
137-
@EJB
138-
private FacilityFacadeEjbLocal facilityFacade;
139-
@EJB
140-
private PersonFacadeEjbLocal personFacade;
141-
@EJB
142-
private PersonService personService;
143-
@EJB
144-
private HospitalizationService hospitalizationService;
145-
@EJB
146-
private EpiDataService epiDataService;
147-
@EJB
148100
private FeatureConfigurationFacadeEjbLocal featureConfigurationFacade;
101+
@EJB
102+
private DiseaseConfigurationFacade diseaseConfigurationFacade;
149103

150104
private static final String CASE_IMPORT_TEMPLATE_FILE_NAME = ImportExportUtils.FILE_PREFIX + "_import_case_template.csv";
151105
private static final String CASE_CONTACT_IMPORT_TEMPLATE_FILE_NAME = ImportExportUtils.FILE_PREFIX + "_import_case_contact_template.csv";
@@ -239,7 +193,7 @@ public void generateCaseLineListingImportTemplateFile() throws IOException {
239193

240194
@Override
241195
public void generatePointOfEntryImportTemplateFile() throws IOException {
242-
generateImportTemplateFile(PointOfEntryDto.class, Paths.get(getPointOfEntryImportTemplateFilePath()), PointOfEntryDto.I18N_PREFIX);
196+
generateImportTemplateFile(PointOfEntryDto.class, Paths.get(getPointOfEntryImportTemplateFilePath()));
243197
}
244198

245199
@Override
@@ -277,30 +231,30 @@ private void createExportDirectoryIfNecessary() throws IOException {
277231

278232
@Override
279233
public void generateAreaImportTemplateFile() throws IOException {
280-
generateImportTemplateFile(AreaDto.class, Paths.get(getAreaImportTemplateFilePath()), AreaDto.I18N_PREFIX);
234+
generateImportTemplateFile(AreaDto.class, Paths.get(getAreaImportTemplateFilePath()));
281235
}
282236

283237
@Override
284238
public void generateRegionImportTemplateFile() throws IOException {
285-
generateImportTemplateFile(RegionDto.class, Paths.get(getRegionImportTemplateFilePath()), RegionDto.I18N_PREFIX);
239+
generateImportTemplateFile(RegionDto.class, Paths.get(getRegionImportTemplateFilePath()));
286240
}
287241

288242
@Override
289243
public void generateDistrictImportTemplateFile() throws IOException {
290-
generateImportTemplateFile(DistrictDto.class, Paths.get(getDistrictImportTemplateFilePath()), DistrictDto.I18N_PREFIX);
244+
generateImportTemplateFile(DistrictDto.class, Paths.get(getDistrictImportTemplateFilePath()));
291245
}
292246

293247
@Override
294248
public void generateCommunityImportTemplateFile() throws IOException {
295-
generateImportTemplateFile(CommunityDto.class, Paths.get(getCommunityImportTemplateFilePath()), CommunityDto.I18N_PREFIX);
249+
generateImportTemplateFile(CommunityDto.class, Paths.get(getCommunityImportTemplateFilePath()));
296250
}
297251

298252
@Override
299253
public void generateFacilityImportTemplateFile() throws IOException {
300-
generateImportTemplateFile(FacilityDto.class, Paths.get(getFacilityImportTemplateFilePath()), FacilityDto.I18N_PREFIX);
254+
generateImportTemplateFile(FacilityDto.class, Paths.get(getFacilityImportTemplateFilePath()));
301255
}
302256

303-
private <T extends EntityDto> void generateImportTemplateFile(Class<T> clazz, Path filePath, String i18nPrefix) throws IOException {
257+
private <T extends EntityDto> void generateImportTemplateFile(Class<T> clazz, Path filePath) throws IOException {
304258

305259
createExportDirectoryIfNecessary();
306260

@@ -433,8 +387,8 @@ private void appendListOfFields(List<ImportColumn> importColumns, Class<?> clazz
433387
// Fields that are depending on a certain feature type to be active may be ignored
434388
if (readMethod.isAnnotationPresent(DependingOnFeatureType.class)) {
435389
List<FeatureType> activeServerFeatures = featureConfigurationFacade.getActiveServerFeatureTypes();
436-
if (!activeServerFeatures.isEmpty()
437-
&& !activeServerFeatures.contains(readMethod.getAnnotation(DependingOnFeatureType.class).featureType())) {
390+
if (!activeServerFeatures.isEmpty() && !activeServerFeatures.contains(readMethod.getAnnotation(DependingOnFeatureType.class)
391+
.featureType())) {
438392
continue;
439393
}
440394
}
@@ -448,13 +402,11 @@ private void appendListOfFields(List<ImportColumn> importColumns, Class<?> clazz
448402
}
449403
// Other non-infrastructure EntityDto/ReferenceDto classes, recursively call this method to include fields of the sub-entity
450404
if (EntityDto.class.isAssignableFrom(field.getType()) && !isInfrastructureClass(field.getType())) {
451-
appendListOfFields(
452-
importColumns,
405+
appendListOfFields(importColumns,
453406
field.getType(),
454407
prefix == null || prefix.isEmpty() ? field.getName() + "." : prefix + field.getName() + ".");
455408
} else if (PersonReferenceDto.class.isAssignableFrom(field.getType()) && !isInfrastructureClass(field.getType())) {
456-
appendListOfFields(
457-
importColumns,
409+
appendListOfFields(importColumns,
458410
PersonDto.class,
459411
prefix == null || prefix.isEmpty() ? field.getName() + "." : prefix + field.getName() + ".");
460412
} else {
@@ -465,11 +417,7 @@ private void appendListOfFields(List<ImportColumn> importColumns, Class<?> clazz
465417

466418
private boolean isInfrastructureClass(Class<?> clazz) {
467419

468-
return clazz == RegionReferenceDto.class
469-
|| clazz == DistrictReferenceDto.class
470-
|| clazz == CommunityReferenceDto.class
471-
|| clazz == FacilityReferenceDto.class
472-
|| clazz == PointOfEntryReferenceDto.class;
420+
return clazz == RegionReferenceDto.class || clazz == DistrictReferenceDto.class || clazz == CommunityReferenceDto.class || clazz == FacilityReferenceDto.class || clazz == PointOfEntryReferenceDto.class;
473421
}
474422

475423
@LocalBean
@@ -495,4 +443,24 @@ private void writeTemplate(Path templatePath, List<ImportColumn> importColumns,
495443
writer.flush();
496444
}
497445
}
446+
447+
@Override
448+
public String getImportTemplateContent(String templateFilePath) throws IOException {
449+
Charset charset = StandardCharsets.UTF_8;
450+
String content = new String(Files.readAllBytes(Paths.get(templateFilePath)), charset);
451+
return resolvePlaceholders(content);
452+
}
453+
454+
private String resolvePlaceholders(String content) {
455+
Map<String, Provider<String>> placeholderResolvers = new HashMap<>();
456+
placeholderResolvers.put(ImportFacade.ACTIVE_DISEASES_PLACEHOLDER,
457+
() -> StringUtils.join(diseaseConfigurationFacade.getAllActiveDiseases().stream().map(Disease::getName).collect(Collectors.toList()),
458+
configFacade.getCsvSeparator()));
459+
460+
for (Map.Entry<String, Provider<String>> placeholderResolver : placeholderResolvers.entrySet()) {
461+
content = content.replace(placeholderResolver.getKey(), placeholderResolver.getValue().get());
462+
}
463+
464+
return content;
465+
}
498466
}

sormas-ui/src/main/java/de/symeda/sormas/ui/importer/AbstractImportLayout.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
import com.vaadin.server.ClassResource;
55
import com.vaadin.server.Extension;
66
import com.vaadin.server.FileDownloader;
7+
import com.vaadin.server.Page;
78
import com.vaadin.server.Resource;
89
import com.vaadin.server.StreamResource;
910
import com.vaadin.ui.Button;
11+
import com.vaadin.ui.Notification;
1012
import com.vaadin.ui.UI;
1113
import com.vaadin.ui.themes.ValoTheme;
1214
import com.vaadin.v7.ui.Upload;
1315
import com.vaadin.v7.ui.VerticalLayout;
1416

17+
import de.symeda.sormas.api.FacadeProvider;
1518
import de.symeda.sormas.api.i18n.Captions;
1619
import de.symeda.sormas.api.i18n.I18nProperties;
1720
import de.symeda.sormas.api.i18n.Strings;
@@ -21,6 +24,8 @@
2124
import de.symeda.sormas.ui.utils.CssStyles;
2225
import de.symeda.sormas.ui.utils.DownloadUtil;
2326

27+
import java.io.IOException;
28+
2429
@SuppressWarnings("serial")
2530
public class AbstractImportLayout extends VerticalLayout {
2631

@@ -66,16 +71,21 @@ protected void addDownloadImportTemplateComponent(int step, String templateFileP
6671
Resource buttonIcon = VaadinIcons.DOWNLOAD;
6772
String buttonCaption = I18nProperties.getCaption(Captions.importDownloadImportTemplate);
6873
ImportLayoutComponent importTemplateComponent = new ImportLayoutComponent(step, headline, infoText, buttonIcon, buttonCaption);
69-
StreamResource templateResource = DownloadUtil.createFileStreamResource(
70-
templateFilePath,
71-
templateFileName,
72-
"text/csv",
73-
I18nProperties.getString(Strings.headingTemplateNotAvailable),
74-
I18nProperties.getString(Strings.messageTemplateNotAvailable));
75-
FileDownloader templateFileDownloader = new FileDownloader(templateResource);
76-
templateFileDownloader.extend(importTemplateComponent.getButton());
77-
CssStyles.style(importTemplateComponent, CssStyles.VSPACE_2);
78-
addComponent(importTemplateComponent);
74+
75+
try {
76+
String content = FacadeProvider.getImportFacade().getImportTemplateContent(templateFilePath);
77+
StreamResource templateResource = DownloadUtil.createStringStreamResource(content, templateFileName, "text/csv");
78+
79+
FileDownloader templateFileDownloader = new FileDownloader(templateResource);
80+
templateFileDownloader.extend(importTemplateComponent.getButton());
81+
82+
CssStyles.style(importTemplateComponent, CssStyles.VSPACE_2);
83+
addComponent(importTemplateComponent);
84+
} catch (IOException e) {
85+
new Notification(I18nProperties.getString(Strings.headingTemplateNotAvailable),
86+
I18nProperties.getString(Strings.messageTemplateNotAvailable), Notification.Type.ERROR_MESSAGE, false)
87+
.show(Page.getCurrent());
88+
}
7989
}
8090

8191
protected void addImportCsvComponent(int step, ImportReceiver receiver) {

0 commit comments

Comments
 (0)