blob: 2a0d2d266798adf7e3b358f2b9d0764c5e2e0669 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Sean Muir
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sarp Kaya (NEHTA) - initial API and implementation
*
*******************************************************************************/
package org.eclipse.mdht.uml.cda.ui.editors;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.window.Window;
import org.eclipse.mdht.uml.cda.ui.internal.Activator;
import org.eclipse.mdht.uml.cda.ui.internal.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
public class MDHTPreferences extends PreferencePage implements IWorkbenchPreferencePage {
private static final String NONE = "NONE";
private static final String SELECT_FILTER = "Select Filter By Type";
private static final String CONSOLURI = "http://www.openhealthtools.org/mdht/uml/cda/consol";
private static String CARDINALITY_CHECK_BOX_LABEL = "Show multiplicity after the element name" +
" in the Properties view";
private static String CARDINALITY_CHECK_BOX_TOOLTIP = "Show multiplicity after the element name in the" +
" Properties view. This does not affect the DITA publication (PDF, Online) - " +
"for that, dita-transform.xml needs to be adjusted to say " +
"cardinalityAfterElement=\"true\" in <transformToDita>";
private static String PDF_GEN_DISABLE_CHECK_BOX_LABEL = "Disable built-in PDF generation";
private static String PDF_GEN_DISABLE_CHECK_BOX_TOOLTIP = "Prevent the automatic generation of PDF " +
" files in the workspace. This also removes the PDF Generation context menu option";
public static String CARDINALITY_STORE_VALUE = "CardinalityCheckValue";
public static String PDF_GEN_STORE_VALUE = "DisablePDFCheckValue";
/**
* @TODO
* Column Selection for reports needs to become more robust
* This is currently overloaded to omit or keep both patient DOB and name
* The store value was kept the same to avoid storage issues
*/
public static String OMIT_DOB_STORE_VALUE = "OmitDOBCheckValue";
public static String OMIT_UNITS_STORE_VALUE = "OmitUnitsCheckValue";
public static String OMIT_VALIDATION_STORE_VALUE = "OmitValidationStoreValue";
public static String CDA_REPORT_FILTERS = "CDAReportDefaultFilter";
public static String CDA_REPORT_ACTIVE_FILTER = "CDAReportActiveFilter";
public static final String CDA_REPORT_FILE_NAME_FILTERS = "fileNameFilter";
private static String OMIT_DOB_CHECK_BOX_LABEL = "Omit DOB and Patient Name from XLS Reports";
private static String OMIT_DOB_CHECK_BOX_TOOLTIP = "Do not include DOB and Patient Name in reports";
private static String OMIT_UNITS_CHECK_BOX_TOOLTIP = "Do not include Units of Measure in reports";
private static String OMIT_UNITS_CHECK_BOX_LABEL = "Omit Quantity Units from XLS Reports";
private static String OMIT_VALIDATION_CHECK_BOX_LABEL = "Omit CDA Validation from XLS Reports";
private static String OMIT_VALIDATION_CHECK_BOX_TOOLTIP = "Do not include DCDA Validation in reports";
// org.eclipse.ui.dialogs.EditorSelectionDialog
/**
* FilterListSelectionDialog
* The dialog buttons were not easily accessible to change the text for OK and Cancel
*
* @TODO This might not be the correct way to do this
* @author seanmuir
*
*/
private static class FilterListSelectionDialog extends ElementListSelectionDialog {
private static final String SET_FILTER = "Set Filter";
private static final String CLEAR_FILTER = "Clear Filter";
/**
* @param parent
* @param renderer
*/
public FilterListSelectionDialog(Shell parent, ILabelProvider renderer) {
super(parent, renderer);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.dialogs.SelectionDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
*/
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
getButton(IDialogConstants.CANCEL_ID).setText(CLEAR_FILTER);
getButton(IDialogConstants.OK_ID).setText(SET_FILTER);
}
}
private Button cardinalityCheckBox;
private Button disablePdfGenerationCheckBox;
private Button omitDOBCheckBox;
private Button omitUnitsCheckBox;
private Text cdaReportFilterText;
private CCombo cdaReportFilterCombo;
private Text cdaFileFiltersText;
private Button omitValidationCheckBox;
String cdaReportActivefilter;
Map<String, List<String>> cdaReportfilters = new HashMap<String, List<String>>();
/**
* Creates an new checkbox instance and sets the default
* layout data.
*
* @param group
* the composite in which to create the checkbox
* @param label
* the string to set into the checkbox
* @return the new checkbox
*/
private Button createCheckBox(Composite group, String label, String toolTip) {
Button button = new Button(group, SWT.CHECK | SWT.LEFT);
button.setText(label);
button.setToolTipText(toolTip);
GridData data = new GridData();
button.setLayoutData(data);
return button;
}
FilterListSelectionDialog filterSelectionDialog = null;
private Button setFilterButton;
private Button createAddFilterButton(Composite group, String label, String toolTip) {
Button button = new Button(group, SWT.PUSH | SWT.LEFT);
button.setText(label);
button.setToolTipText(toolTip);
GridData data = new GridData();
button.setLayoutData(data);
button.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
addFilterName("<<FilterName>>", cdaReportfilters.keySet());
}
});
return button;
}
private Button createFilterButton(Composite group, String label, String toolTip) {
ILabelProvider lp = new ILabelProvider() {
@Override
public void addListener(ILabelProviderListener listener) {
}
@Override
public void dispose() {
}
@Override
public boolean isLabelProperty(Object element, String property) {
return false;
}
@Override
public void removeListener(ILabelProviderListener listener) {
}
@Override
public Image getImage(Object element) {
return null;
}
@Override
public String getText(Object element) {
EClass ec = (EClass) element;
String theElementName = ec.getName();
if (Character.isDigit(theElementName.charAt(theElementName.length() - 1))) {
theElementName = theElementName.substring(0, theElementName.length() - 1);
}
String[] nameArray = theElementName.split("(?=\\p{Upper})");
StringBuffer sb = new StringBuffer();
for (String seg : nameArray) {
sb.append(seg).append(" ");
}
sb.append("(s)");
return sb.toString();
}
};
filterSelectionDialog = new FilterListSelectionDialog(group.getShell(), lp);
filterSelectionDialog.setTitle(SELECT_FILTER);
filterSelectionDialog.setMessage(SELECT_FILTER);
final HashMap<EClass, HashSet<EClass>> theSectionCache = new HashMap<EClass, HashSet<EClass>>();
getFilterHash(theSectionCache);
filterSelectionDialog.setElements(theSectionCache.keySet().toArray());
filterSelectionDialog.setMultipleSelection(true);
Button button = new Button(group, SWT.PUSH | SWT.LEFT);
button.setText(label);
button.setToolTipText(toolTip);
GridData data = new GridData();
button.setLayoutData(data);
button.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
String currentSelections = cdaReportFilterText.getText();
final List<EClass> l = new ArrayList<EClass>();
for (Object x : theSectionCache.keySet().toArray()) {
EClass eClass = (EClass) x;
if (currentSelections.contains(formatFilterName(eClass.getName()))) {
l.add(eClass);
}
}
filterSelectionDialog.setInitialElementSelections(l);
switch (filterSelectionDialog.open()) {
case Window.OK:
if (cdaReportfilters.containsKey(cdaReportActivefilter)) {
cdaReportfilters.get(cdaReportActivefilter).clear();
} else {
cdaReportfilters.put(cdaReportActivefilter, new ArrayList<String>());
}
for (Object object : filterSelectionDialog.getResult()) {
cdaReportfilters.get(cdaReportActivefilter).add(((EClass) object).getName());
}
cdaReportFilterText.setText(formatFilterNames(cdaReportfilters.get(cdaReportActivefilter)));
break;
case Window.CANCEL:
cdaReportfilters.get(cdaReportActivefilter).clear();
cdaReportFilterText.setText(NONE);
break;
}
}
});
return button;
}
private String formatFilterNames(List<String> filterNames) {
StringBuilder formattedFilters = new StringBuilder();
if (filterNames != null) {
for (String filter : filterNames) {
if (formattedFilters.length() > 0) {
formattedFilters.append(System.getProperty("line.separator"));
}
formattedFilters.append(formatFilterName(filter));
}
} else {
formattedFilters.append("NONE");
}
return formattedFilters.toString();
}
private String formatFilterName(String filterName) {
StringBuffer formattedFilterName = new StringBuffer();
if (!StringUtils.isEmpty(filterName)) {
if (Character.isDigit(filterName.charAt(filterName.length() - 1))) {
filterName = filterName.substring(0, filterName.length() - 1);
}
String[] nameArray = filterName.split("(?=\\p{Upper})");
for (String seg : nameArray) {
formattedFilterName.append(seg).append(" ");
}
formattedFilterName.append("(s)");
}
return formattedFilterName.toString();
}
/**
* Creates composite control and sets the default layout data.
*
* @param parent
* the parent of the new composite
* @param numColumns
* the number of columns for the new composite
* @return the newly-created coposite
*/
private Composite createComposite(Composite parent, int numColumns) {
Composite composite = new Composite(parent, SWT.NULL);
// GridLayout
GridLayout layout = new GridLayout();
layout.numColumns = numColumns;
composite.setLayout(layout);
// GridData
GridData data = new GridData();
data.verticalAlignment = GridData.FILL;
data.horizontalAlignment = GridData.FILL;
composite.setLayoutData(data);
return composite;
}
/**
* (non-Javadoc)
* Method declared on PreferencePage
*/
@Override
protected Control createContents(Composite parent) {
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "MDHTPreferences");
Composite composite_textField = createComposite(parent, 2);
cardinalityCheckBox = createCheckBox(
composite_textField, CARDINALITY_CHECK_BOX_LABEL, CARDINALITY_CHECK_BOX_TOOLTIP);
Composite pdf_composite_textField = createComposite(parent, 2);
disablePdfGenerationCheckBox = createCheckBox(
pdf_composite_textField, PDF_GEN_DISABLE_CHECK_BOX_LABEL, PDF_GEN_DISABLE_CHECK_BOX_TOOLTIP);
Composite dob_composite_textField = createComposite(parent, 2);
omitDOBCheckBox = createCheckBox(dob_composite_textField, OMIT_DOB_CHECK_BOX_LABEL, OMIT_DOB_CHECK_BOX_TOOLTIP);
Composite validateion_composite_textField = createComposite(parent, 2);
omitValidationCheckBox = createCheckBox(
validateion_composite_textField, OMIT_VALIDATION_CHECK_BOX_LABEL, OMIT_VALIDATION_CHECK_BOX_TOOLTIP);
Composite units_composite_textField = createComposite(parent, 2);
omitUnitsCheckBox = createCheckBox(
units_composite_textField, OMIT_UNITS_CHECK_BOX_LABEL, OMIT_UNITS_CHECK_BOX_TOOLTIP);
// Need to call ths before combo set up but after check box setups - bad design swm
initializeValues();
Composite filterLabelComposite = createComposite(parent, 2);
Label filterLabel = new Label(filterLabelComposite, SWT.LEFT);
filterLabel.setText("Report Section Filters");
Composite filterComboLabelComposite = createComposite(parent, 2);
Label filterComboLabel = new Label(filterComboLabelComposite, SWT.LEFT);
filterComboLabel.setText("Active Filter");
Composite filter_Combo = createComposite(parent, 1);
cdaReportFilterCombo = new CCombo(filter_Combo, SWT.READ_ONLY);
String[] items = cdaReportfilters.keySet().stream().toArray(String[]::new);
if (items.length == 0) {
ArrayList<String> noneList = new ArrayList<String>();
noneList.add(NONE);
items = noneList.toArray(String[]::new);
}
cdaReportFilterCombo.setItems(items);
cdaReportFilterCombo.select(Arrays.asList(cdaReportFilterCombo.getItems()).indexOf(this.cdaReportActivefilter));
cdaReportFilterCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Logger.log(
Logger.INFO,
"Selection: " + cdaReportFilterCombo.getItem(cdaReportFilterCombo.getSelectionIndex()));
cdaReportActivefilter = cdaReportFilterCombo.getItem(cdaReportFilterCombo.getSelectionIndex());
cdaReportFilterText.setText(formatFilterNames(cdaReportfilters.get(cdaReportActivefilter)));
if (cdaReportActivefilter.equals("NONE") || StringUtils.isEmpty(cdaReportActivefilter)) {
setFilterButton.setEnabled(false);
} else {
setFilterButton.setEnabled(true);
}
}
});
Composite filter_text = createComposite(parent, 1);
cdaReportFilterText = new Text(filter_text, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.LEFT);
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.heightHint = 50;
cdaReportFilterText.setLayoutData(gd);
cdaReportFilterText.setEditable(false);
Composite filter_composite = createComposite(parent, 2);
setFilterButton = createFilterButton(
filter_composite, "Set Section Filters", "Set the Section filters for CDA spreadsheet");
if (this.cdaReportActivefilter.equals("NONE") || StringUtils.isEmpty(cdaReportActivefilter)) {
setFilterButton.setEnabled(false);
} else {
setFilterButton.setEnabled(true);
}
Composite addFilter_composite = createComposite(parent, 3);
createAddFilterButton(addFilter_composite, "Add Filters", "Add filter for CDA spreadsheet");
cdaReportFilterText.setText(formatFilterNames(cdaReportfilters.get(cdaReportActivefilter)));
return new Composite(parent, SWT.NULL);
}
/**
* The <code>ReadmePreferencePage</code> implementation of this <code>PreferencePage</code> method
* returns preference store that belongs to the our plugin.
* This is important because we want to store
* our preferences separately from the workbench.
*/
@Override
protected IPreferenceStore doGetPreferenceStore() {
return Activator.getDefault().getPreferenceStore();
}
public void init(IWorkbench workbench) {
}
/**
* Initializes states of the controls using default values
* in the preference store.
*/
private void initializeDefaults() {
IPreferenceStore store = getPreferenceStore();
cardinalityCheckBox.setSelection(store.getDefaultBoolean(CARDINALITY_STORE_VALUE));
disablePdfGenerationCheckBox.setSelection(store.getBoolean(PDF_GEN_STORE_VALUE));
omitDOBCheckBox.setSelection(store.getBoolean(OMIT_DOB_STORE_VALUE));
omitUnitsCheckBox.setSelection(store.getBoolean(OMIT_UNITS_STORE_VALUE));
omitValidationCheckBox.setSelection(store.getBoolean(OMIT_VALIDATION_STORE_VALUE));
cdaReportFilterText.setText(NONE);
cdaReportActivefilter = NONE;
}
/**
* Initializes states of the controls from the preference store.
*/
private void initializeValues() {
IPreferenceStore store = getPreferenceStore();
cardinalityCheckBox.setSelection(store.getBoolean(CARDINALITY_STORE_VALUE));
disablePdfGenerationCheckBox.setSelection(store.getBoolean(PDF_GEN_STORE_VALUE));
omitDOBCheckBox.setSelection(store.getBoolean(OMIT_DOB_STORE_VALUE));
omitUnitsCheckBox.setSelection(store.getBoolean(OMIT_UNITS_STORE_VALUE));
omitValidationCheckBox.setSelection(store.getBoolean(OMIT_VALIDATION_STORE_VALUE));
filtersFromString(store.getString(CDA_REPORT_FILTERS), cdaReportfilters);
for (String k3 : cdaReportfilters.keySet()) {
Logger.log(Logger.INFO, "LOOPNG " + k3);
Logger.log(Logger.INFO, "VALUE " + cdaReportfilters.get(k3));
}
cdaReportActivefilter = store.getString(CDA_REPORT_ACTIVE_FILTER);
// cdaReportActivefilter = DEFAULT;
Logger.log(Logger.INFO, "READING " + cdaReportActivefilter);
if (StringUtils.isEmpty(cdaReportActivefilter)) {
cdaReportActivefilter = NONE;
}
}
@Override
protected void performDefaults() {
super.performDefaults();
initializeDefaults();
}
@Override
public boolean performOk() {
storeValues();
return true;
}
/**
* Stores the values of the controls back to the preference store.
*/
private void storeValues() {
IPreferenceStore store = getPreferenceStore();
store.setValue(CARDINALITY_STORE_VALUE, cardinalityCheckBox.getSelection());
store.setValue(PDF_GEN_STORE_VALUE, disablePdfGenerationCheckBox.getSelection());
store.setValue(OMIT_DOB_STORE_VALUE, omitDOBCheckBox.getSelection());
store.setValue(OMIT_UNITS_STORE_VALUE, omitUnitsCheckBox.getSelection());
store.setValue(OMIT_VALIDATION_STORE_VALUE, omitValidationCheckBox.getSelection());
store.setValue(CDA_REPORT_FILTERS, filtersToString(cdaReportfilters));
store.setValue(CDA_REPORT_FILE_NAME_FILTERS, "C62TXT");
store.setValue(CDA_REPORT_ACTIVE_FILTER, cdaReportActivefilter);
}
private static String filtersToString(Map<String, List<String>> map) {
String mapAsString = map.keySet().stream().map(
key -> key + "=" + " " + String.join(" ", map.get(key)) + " ").collect(Collectors.joining(", ", " ", " "));
Logger.log(Logger.INFO, "STORING " + mapAsString);
return mapAsString;
}
public static void filtersFromString(String mapAsString, Map<String, List<String>> filters) {
filters.clear();
Logger.log(Logger.INFO, "READING " + mapAsString);
if (mapAsString.contains("=")) {
Map<String, String> map1 = Arrays.stream(mapAsString.split(",")).map(entry -> entry.split("=")).collect(
Collectors.toMap(entry -> entry[0], entry -> entry[1]));
for (String k : map1.keySet()) {
String key = StringUtils.trim(k);
filters.put(key, new ArrayList<String>());
filters.get(key).addAll(Arrays.asList(map1.get(k).split(" ")));
}
} else {
filters.put(NONE, new ArrayList<String>());
filters.get(NONE).addAll(Arrays.asList(mapAsString.split(" ")));
}
}
void getFilterHash(HashMap<EClass, HashSet<EClass>> theSections) {
EPackage consolPackage = EPackage.Registry.INSTANCE.getEPackage(CONSOLURI);
TreeIterator<EObject> packageContents = consolPackage.eAllContents();
ArrayList<EClass> packageSections = new ArrayList<EClass>();
ArrayList<EClass> rootSections = new ArrayList<EClass>();
while (packageContents.hasNext()) {
EObject packageObject = packageContents.next();
if (packageObject instanceof EClass) {
EClass eClass = (EClass) packageObject;
boolean isSection = false;
for (EClass eClass2 : eClass.getEAllSuperTypes()) {
if ("Section".equals(eClass2.getName())) {
isSection = true;
break;
}
}
if (isSection) {
packageSections.add(eClass);
}
}
}
Set<EClass> sectionBaseClasses = new HashSet<EClass>();
for (EClass section : packageSections) {
for (EClass parentSection : section.getESuperTypes()) {
sectionBaseClasses.add(parentSection);
}
}
Comparator<? super EClass> compare = new Comparator<EClass>() {
@Override
public int compare(EClass o1, EClass o2) {
return o1.getName().compareTo(o2.getName());
}
};
Collections.sort(packageSections, compare);
for (EClass section : packageSections) {
if (!sectionBaseClasses.contains(section)) {
boolean isRealRoot = true;
for (EClass sectionAgain : packageSections) {
if (sectionAgain.getName().startsWith(section.getName()) &&
!sectionAgain.getName().equals(section.getName())) {
isRealRoot = false;
}
}
if (isRealRoot) {
rootSections.add(section);
}
}
}
for (EClass ec3 : rootSections) {
theSections.put(ec3, new HashSet<EClass>());
theSections.get(ec3).addAll(ec3.getEAllSuperTypes());
theSections.get(ec3).add(ec3);
for (EClass sectionAgain : packageSections) {
if (ec3.getName().startsWith(sectionAgain.getName()) && !ec3.getName().equals(sectionAgain.getName())) {
theSections.get(ec3).add(sectionAgain);
}
}
}
}
private void addFilterName(String initialName, final Set<String> usedNames) {
InputDialog dlg = new InputDialog(
getShell(), "Add New Filter", "Enter Filter Name : ", initialName, new IInputValidator() {
@Override
public String isValid(String newText) {
newText = newText.trim();
if (newText.isEmpty()) {
return "EMPTY";
} else if (usedNames.contains(newText)) {
return "FILTER EXISTS";
}
return null;
}
});
if (dlg.open() == Window.OK) {
cdaReportActivefilter = dlg.getValue().trim();
Logger.log(Logger.INFO, "cdaReportActivefilter >>>" + cdaReportActivefilter);
ArrayList<String> filters = new ArrayList<String>();
filters.addAll(Arrays.asList(cdaReportFilterCombo.getItems()));
filters.add(cdaReportActivefilter);
for (String filter : filters) {
Logger.log(Logger.INFO, "filter >>>" + filter);
}
cdaReportFilterCombo.setItems(filters.toArray(String[]::new));
cdaReportFilterCombo.redraw();
cdaReportFilterCombo.select(
Arrays.asList(cdaReportFilterCombo.getItems()).indexOf(this.cdaReportActivefilter));
if (cdaReportActivefilter.equals("NONE") || StringUtils.isEmpty(cdaReportActivefilter)) {
setFilterButton.setEnabled(false);
} else {
setFilterButton.setEnabled(true);
}
}
}
}