de.symeda.sormas.api.doc.DataDictionaryGenerator.java Source code

Java tutorial

Introduction

Here is the source code for de.symeda.sormas.api.doc.DataDictionaryGenerator.java

Source

/*******************************************************************************
 * SORMAS - Surveillance Outbreak Response Management & Analysis System
 * Copyright  2016-2018 Helmholtz-Zentrum fr Infektionsforschung GmbH (HZI)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *******************************************************************************/
package de.symeda.sormas.api.doc;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;

import de.symeda.sormas.api.Disease;
import de.symeda.sormas.api.EntityDto;
import de.symeda.sormas.api.ReferenceDto;
import de.symeda.sormas.api.caze.CaseDataDto;
import de.symeda.sormas.api.clinicalcourse.ClinicalVisitDto;
import de.symeda.sormas.api.clinicalcourse.HealthConditionsDto;
import de.symeda.sormas.api.contact.ContactDto;
import de.symeda.sormas.api.epidata.EpiDataDto;
import de.symeda.sormas.api.event.EventDto;
import de.symeda.sormas.api.event.EventParticipantDto;
import de.symeda.sormas.api.facility.FacilityDto;
import de.symeda.sormas.api.hospitalization.HospitalizationDto;
import de.symeda.sormas.api.i18n.I18nProperties;
import de.symeda.sormas.api.location.LocationDto;
import de.symeda.sormas.api.person.PersonDto;
import de.symeda.sormas.api.region.CommunityDto;
import de.symeda.sormas.api.region.DistrictDto;
import de.symeda.sormas.api.region.RegionDto;
import de.symeda.sormas.api.sample.AdditionalTestDto;
import de.symeda.sormas.api.sample.PathogenTestDto;
import de.symeda.sormas.api.sample.SampleDto;
import de.symeda.sormas.api.symptoms.SymptomsDto;
import de.symeda.sormas.api.task.TaskDto;
import de.symeda.sormas.api.therapy.PrescriptionDto;
import de.symeda.sormas.api.therapy.TreatmentDto;
import de.symeda.sormas.api.user.UserDto;
import de.symeda.sormas.api.utils.DataHelper;
import de.symeda.sormas.api.utils.Diseases;
import de.symeda.sormas.api.utils.Outbreaks;
import de.symeda.sormas.api.utils.Required;
import de.symeda.sormas.api.visit.VisitDto;

/**
 * Intentionally named *Generator because we don't want Maven to execute this
 * class automatically.
 */
public class DataDictionaryGenerator {

    @Test
    public void generateDataDictionary() throws FileNotFoundException, IOException {

        XSSFWorkbook workbook = new XSSFWorkbook();

        createEntitySheet(workbook, PersonDto.class, PersonDto.I18N_PREFIX);
        createEntitySheet(workbook, LocationDto.class, LocationDto.I18N_PREFIX);
        createEntitySheet(workbook, CaseDataDto.class, CaseDataDto.I18N_PREFIX);
        createEntitySheet(workbook, HospitalizationDto.class, HospitalizationDto.I18N_PREFIX);
        createEntitySheet(workbook, SymptomsDto.class, SymptomsDto.I18N_PREFIX);
        createEntitySheet(workbook, EpiDataDto.class, EpiDataDto.I18N_PREFIX);
        createEntitySheet(workbook, HealthConditionsDto.class, HealthConditionsDto.I18N_PREFIX);
        createEntitySheet(workbook, PrescriptionDto.class, PrescriptionDto.I18N_PREFIX);
        createEntitySheet(workbook, TreatmentDto.class, TreatmentDto.I18N_PREFIX);
        createEntitySheet(workbook, ClinicalVisitDto.class, ClinicalVisitDto.I18N_PREFIX);
        createEntitySheet(workbook, ContactDto.class, ContactDto.I18N_PREFIX);
        createEntitySheet(workbook, VisitDto.class, VisitDto.I18N_PREFIX);
        createEntitySheet(workbook, SampleDto.class, SampleDto.I18N_PREFIX);
        createEntitySheet(workbook, PathogenTestDto.class, PathogenTestDto.I18N_PREFIX);
        createEntitySheet(workbook, AdditionalTestDto.class, AdditionalTestDto.I18N_PREFIX);
        createEntitySheet(workbook, TaskDto.class, TaskDto.I18N_PREFIX);
        createEntitySheet(workbook, EventDto.class, EventDto.I18N_PREFIX);
        createEntitySheet(workbook, EventParticipantDto.class, EventParticipantDto.I18N_PREFIX);
        createEntitySheet(workbook, FacilityDto.class, FacilityDto.I18N_PREFIX);
        createEntitySheet(workbook, RegionDto.class, RegionDto.I18N_PREFIX);
        createEntitySheet(workbook, DistrictDto.class, DistrictDto.I18N_PREFIX);
        createEntitySheet(workbook, CommunityDto.class, CommunityDto.I18N_PREFIX);
        createEntitySheet(workbook, UserDto.class, UserDto.I18N_PREFIX);

        XssfHelper.addAboutSheet(workbook);

        String filePath = "src/main/resources/doc/SORMAS_Data_Dictionary.xlsx";
        try (OutputStream fileOut = new FileOutputStream(filePath)) {
            workbook.write(fileOut);
        }
        workbook.close();
    }

    private enum EntityColumn {
        FIELD, TYPE, CAPTION, DESCRIPTION, REQUIRED, DISEASES, OUTBREAKS,
    }

    @SuppressWarnings("unchecked")
    private XSSFSheet createEntitySheet(XSSFWorkbook workbook, Class<? extends EntityDto> entityClass,
            String i18nPrefix) {
        String name = I18nProperties.getCaption(i18nPrefix);
        String safeName = WorkbookUtil.createSafeSheetName(name);
        XSSFSheet sheet = workbook.createSheet(safeName);

        // Create
        XSSFTable table = sheet.createTable();
        String safeTableName = safeName.replaceAll("\\s", "_");
        table.setName(safeTableName);
        table.setDisplayName(safeTableName);

        XssfHelper.styleTable(table, 1);

        int columnCount = EntityColumn.values().length;
        int rowNumber = 0;
        // header
        XSSFRow headerRow = sheet.createRow(rowNumber++);
        for (EntityColumn column : EntityColumn.values()) {
            table.addColumn();
            String columnCaption = column.toString();
            columnCaption = columnCaption.substring(0, 1) + columnCaption.substring(1).toLowerCase();
            headerRow.createCell(column.ordinal()).setCellValue(columnCaption);
        }

        // column width
        sheet.setColumnWidth(EntityColumn.FIELD.ordinal(), 256 * 30);
        sheet.setColumnWidth(EntityColumn.TYPE.ordinal(), 256 * 30);
        sheet.setColumnWidth(EntityColumn.CAPTION.ordinal(), 256 * 30);
        sheet.setColumnWidth(EntityColumn.DESCRIPTION.ordinal(), 256 * 60);
        sheet.setColumnWidth(EntityColumn.REQUIRED.ordinal(), 256 * 10);
        sheet.setColumnWidth(EntityColumn.DISEASES.ordinal(), 256 * 45);
        sheet.setColumnWidth(EntityColumn.OUTBREAKS.ordinal(), 256 * 10);

        CellStyle defaultCellStyle = workbook.createCellStyle();
        defaultCellStyle.setWrapText(true);

        List<Class<Enum<?>>> usedEnums = new ArrayList<Class<Enum<?>>>();

        for (Field field : entityClass.getDeclaredFields()) {
            if (java.lang.reflect.Modifier.isStatic(field.getModifiers()))
                continue;
            XSSFRow row = sheet.createRow(rowNumber++);

            // field name
            XSSFCell fieldNameCell = row.createCell(EntityColumn.FIELD.ordinal());
            fieldNameCell.setCellValue(field.getName());

            // value range
            XSSFCell fieldValueCell = row.createCell(EntityColumn.TYPE.ordinal());
            fieldValueCell.setCellStyle(defaultCellStyle);
            Class<?> fieldType = field.getType();
            if (fieldType.isEnum()) {
                // use enum type name - values are added below
                //            Object[] enumValues = fieldType.getEnumConstants();
                //            StringBuilder valuesString = new StringBuilder();
                //            for (Object enumValue : enumValues) {
                //               if (valuesString.length() > 0)
                //                  valuesString.append(", ");
                //               valuesString.append(((Enum) enumValue).name());
                //            }
                //            fieldValueCell.setCellValue(valuesString.toString());
                fieldValueCell.setCellValue(fieldType.getSimpleName());
                if (!usedEnums.contains(fieldType)) {
                    usedEnums.add((Class<Enum<?>>) fieldType);
                }
            } else if (EntityDto.class.isAssignableFrom(fieldType)) {
                fieldValueCell.setCellValue(fieldType.getSimpleName().replaceAll("Dto", ""));
            } else if (ReferenceDto.class.isAssignableFrom(fieldType)) {
                fieldValueCell.setCellValue(fieldType.getSimpleName().replaceAll("Dto", ""));
            } else if (String.class.isAssignableFrom(fieldType)) {
                fieldValueCell.setCellValue(I18nProperties.getCaption("text"));
            } else if (Date.class.isAssignableFrom(fieldType)) {
                fieldValueCell.setCellValue(I18nProperties.getCaption("date"));
            } else if (Number.class.isAssignableFrom(fieldType)) {
                fieldValueCell.setCellValue(I18nProperties.getCaption("number"));
            } else if (Boolean.class.isAssignableFrom(fieldType) || boolean.class.isAssignableFrom(fieldType)) {
                fieldValueCell.setCellValue(Boolean.TRUE.toString() + ", " + Boolean.FALSE.toString());
            }

            // caption
            XSSFCell captionCell = row.createCell(EntityColumn.CAPTION.ordinal());
            captionCell.setCellValue(I18nProperties.getPrefixCaption(i18nPrefix, field.getName(), ""));

            // description
            XSSFCell descriptionCell = row.createCell(EntityColumn.DESCRIPTION.ordinal());
            descriptionCell.setCellStyle(defaultCellStyle);
            descriptionCell.setCellValue(I18nProperties.getPrefixDescription(i18nPrefix, field.getName(), ""));

            // required
            XSSFCell requiredCell = row.createCell(EntityColumn.REQUIRED.ordinal());
            if (field.getAnnotation(Required.class) != null)
                requiredCell.setCellValue(true);

            // diseases
            XSSFCell diseasesCell = row.createCell(EntityColumn.DISEASES.ordinal());
            diseasesCell.setCellStyle(defaultCellStyle);
            Diseases diseases = field.getAnnotation(Diseases.class);
            if (diseases != null) {
                StringBuilder diseasesString = new StringBuilder();
                for (Disease disease : diseases.value()) {
                    if (diseasesString.length() > 0)
                        diseasesString.append(", ");
                    diseasesString.append(disease.toShortString());
                }
                diseasesCell.setCellValue(diseasesString.toString());
            } else {
                diseasesCell.setCellValue("All");
            }

            // outbreak
            XSSFCell outbreakCell = row.createCell(EntityColumn.OUTBREAKS.ordinal());
            if (field.getAnnotation(Outbreaks.class) != null)
                outbreakCell.setCellValue(true);
        }

        AreaReference reference = workbook.getCreationHelper().createAreaReference(new CellReference(0, 0),
                new CellReference(rowNumber - 1, columnCount - 1));
        table.setCellReferences(reference);
        table.getCTTable().addNewAutoFilter();

        for (Class<Enum<?>> usedEnum : usedEnums) {
            rowNumber = createEnumTable(sheet, rowNumber + 1, usedEnum);
        }

        return sheet;
    }

    private enum EnumColumn {
        TYPE, VALUE, CAPTION, DESCRIPTION, SHORT
    }

    private int createEnumTable(XSSFSheet sheet, int startRow, Class<Enum<?>> enumType) {

        // Create
        XSSFTable table = sheet.createTable();
        String safeTableName = (sheet.getSheetName() + enumType.getSimpleName()).replaceAll("\\s", "_");
        table.setName(safeTableName);
        table.setDisplayName(safeTableName);
        XssfHelper.styleTable(table, 2);

        int columnCount = EnumColumn.values().length;
        int rowNumber = startRow;

        // header
        XSSFRow headerRow = sheet.createRow(rowNumber++);
        for (EnumColumn column : EnumColumn.values()) {
            table.addColumn();
            String columnCaption = column.toString();
            columnCaption = columnCaption.substring(0, 1) + columnCaption.substring(1).toLowerCase();
            headerRow.createCell(column.ordinal()).setCellValue(columnCaption);
        }

        Object[] enumValues = enumType.getEnumConstants();
        for (Object enumValueObject : enumValues) {
            XSSFRow row = sheet.createRow(rowNumber++);
            XSSFCell cell;
            Enum<?> enumValue = ((Enum<?>) enumValueObject);

            cell = row.createCell(EnumColumn.TYPE.ordinal());
            if (enumValueObject == enumValues[0]) {
                cell.setCellValue(enumType.getSimpleName());
            }

            cell = row.createCell(EnumColumn.VALUE.ordinal());
            cell.setCellValue(enumValue.name());

            cell = row.createCell(EnumColumn.CAPTION.ordinal());
            String caption = enumValue.toString();
            cell.setCellValue(caption);

            cell = row.createCell(EnumColumn.DESCRIPTION.ordinal());
            String desc = I18nProperties.getEnumDescription(enumValue);
            cell.setCellValue(DataHelper.equal(caption, desc) ? "" : desc);

            cell = row.createCell(EnumColumn.SHORT.ordinal());
            String shortCaption = I18nProperties.getEnumCaptionShort(enumValue);
            cell.setCellValue(DataHelper.equal(caption, shortCaption) ? "" : shortCaption);
        }

        AreaReference reference = new AreaReference(new CellReference(startRow, 0),
                new CellReference(rowNumber - 1, columnCount - 1), SpreadsheetVersion.EXCEL2007);
        table.setCellReferences(reference);
        table.getCTTable().addNewAutoFilter();

        return rowNumber;
    }
}