From 71169ed748fcdd2a4f72066ef9ab22db8ca34518 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 17:14:51 +0100 Subject: [PATCH 01/17] bump snapshot version --- src/org/ohdsi/usagi/ui/UsagiMain.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/ohdsi/usagi/ui/UsagiMain.java b/src/org/ohdsi/usagi/ui/UsagiMain.java index 7f4f94d..108cc65 100644 --- a/src/org/ohdsi/usagi/ui/UsagiMain.java +++ b/src/org/ohdsi/usagi/ui/UsagiMain.java @@ -41,7 +41,7 @@ */ public class UsagiMain implements ActionListener { - public static String version = "1.4.1"; + public static String version = "1.4.2-SNAPSHOT"; public static void main(String[] args) { new UsagiMain(args); From c808699033ff5aad4a0cc4c744b053838753a6cc Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 17:32:36 +0100 Subject: [PATCH 02/17] add value and unit buttons on the left of the button panel --- .../ohdsi/usagi/ui/MappingDetailPanel.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/MappingDetailPanel.java b/src/org/ohdsi/usagi/ui/MappingDetailPanel.java index c42b06f..fbe1a16 100644 --- a/src/org/ohdsi/usagi/ui/MappingDetailPanel.java +++ b/src/org/ohdsi/usagi/ui/MappingDetailPanel.java @@ -21,8 +21,6 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.util.*; import java.util.Timer; @@ -204,13 +202,10 @@ private Component createSearchResultsPanel() { replaceButton = new JButton("Replace concept"); replaceButton.setToolTipText("Replace selected concept"); - replaceButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int viewRow = searchTable.getSelectedRow(); - int modelRow = searchTable.convertRowIndexToModel(viewRow); - replaceConcepts(searchTableModel.getConcept(modelRow)); - } - + replaceButton.addActionListener(e -> { + int viewRow = searchTable.getSelectedRow(); + int modelRow = searchTable.convertRowIndexToModel(viewRow); + replaceConcepts(searchTableModel.getConcept(modelRow)); }); replaceButton.setEnabled(false); buttonPanel.add(replaceButton); @@ -231,7 +226,12 @@ public void actionPerformed(ActionEvent e) { }); button.setEnabled(false); addButtons.add(button); - buttonPanel.add(button); + // Add Maps_to button on the right, the other on the left. + if (mappingType.equals(MappingTarget.Type.MAPS_TO)) { + buttonPanel.add(button); + } else { + buttonPanel.add(button, 0); + } } panel.add(buttonPanel); From f6ede00d45cf4c11de8ca49533eadc6a8f1f68d0 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 18:11:26 +0100 Subject: [PATCH 03/17] enable add/replace buttons upon unapproving --- src/org/ohdsi/usagi/ui/MappingDetailPanel.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/org/ohdsi/usagi/ui/MappingDetailPanel.java b/src/org/ohdsi/usagi/ui/MappingDetailPanel.java index fbe1a16..d93155e 100644 --- a/src/org/ohdsi/usagi/ui/MappingDetailPanel.java +++ b/src/org/ohdsi/usagi/ui/MappingDetailPanel.java @@ -443,6 +443,11 @@ public void uncheckSelected() { } else { Global.mapping.fireDataChanged(MULTI_UPDATE_EVENT); } + // If a row selected, then enable the add buttons + if (searchTable.getSelectedRow() != -1) { + replaceButton.setEnabled(true); + addButtons.forEach(x -> x.setEnabled(true)); + } } private void toggleStatusButtons() { From e11d4b0eb75f73994768140d3d8385d2d7163c42 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 18:14:04 +0100 Subject: [PATCH 04/17] move typeChooser of existing target to left of button panel --- src/org/ohdsi/usagi/ui/MappingDetailPanel.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/org/ohdsi/usagi/ui/MappingDetailPanel.java b/src/org/ohdsi/usagi/ui/MappingDetailPanel.java index d93155e..8259b47 100644 --- a/src/org/ohdsi/usagi/ui/MappingDetailPanel.java +++ b/src/org/ohdsi/usagi/ui/MappingDetailPanel.java @@ -348,7 +348,6 @@ private JPanel createTargetConceptsPanel() { JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); - buttonPanel.add(Box.createHorizontalGlue()); typesChooser = new JComboBox<>(MappingTarget.Type.values()); typesChooser.setToolTipText("Set type of the mapping"); @@ -360,6 +359,8 @@ private JPanel createTargetConceptsPanel() { typesChooser.setEnabled(false); buttonPanel.add(typesChooser); + buttonPanel.add(Box.createHorizontalGlue()); + removeButton = new JButton("Remove concept"); removeButton.setToolTipText("Remove selected concept"); removeButton.addActionListener(e -> remove()); From 920f726ed77cd81705aad37878cdd3be9ae4a00e Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 18:41:28 +0100 Subject: [PATCH 05/17] add current concept in between parent and child in the concept detail window --- .../usagi/ui/ConceptInformationDialog.java | 126 +++++++++--------- 1 file changed, 60 insertions(+), 66 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java index 075cc21..7c8a301 100644 --- a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java +++ b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java @@ -23,6 +23,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.swing.BorderFactory; @@ -55,6 +56,8 @@ public class ConceptInformationDialog extends JFrame { private JButton forwardButton; private ConceptTableModel parentConceptTableModel; private UsagiTable parentsConceptTable; + private ConceptTableModel currentConceptTableModel; + private UsagiTable currentConceptTable; private ConceptTableModel childrenConceptTableModel; private UsagiTable childrenConceptTable; private ConceptTableModel sourceConceptTableModel; @@ -98,7 +101,7 @@ private Component createSourceConceptPanel() { sourceConceptTable.setPreferredScrollableViewportSize(new Dimension(500, 45)); sourceConceptTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); sourceConceptTable.setRowSelectionAllowed(false); - sourceConceptTable.setRowSorter(new TableRowSorter(sourceConceptTableModel)); + sourceConceptTable.setRowSorter(new TableRowSorter<>(sourceConceptTableModel)); sourceConceptTable.hideColumn("Parents"); sourceConceptTable.hideColumn("Children"); sourceConceptTable.hideColumn("Valid start date"); @@ -121,79 +124,82 @@ private Component createHierarchyPanel() { c.weightx = 1; parentConceptTableModel = new ConceptTableModel(false); - parentsConceptTable = new UsagiTable(parentConceptTableModel); - parentsConceptTable.setRowSorter(new TableRowSorter(parentConceptTableModel)); - parentsConceptTable.setPreferredScrollableViewportSize(new Dimension(500, 45)); - parentsConceptTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - parentsConceptTable.setRowSelectionAllowed(true); - parentsConceptTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - parentsConceptTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent event) { - if (!updating) { - updating = true; - int viewRow = parentsConceptTable.getSelectedRow(); - Global.conceptInfoAction.setEnabled(true); - int modelRow = parentsConceptTable.convertRowIndexToModel(viewRow); - Global.conceptInformationDialog.setConcept(parentConceptTableModel.getConcept(modelRow)); - updating = false; - } + parentsConceptTable = hierarchyTableBuilder(parentConceptTableModel); + currentConceptTable.setRowSelectionAllowed(true); + parentsConceptTable.getSelectionModel().addListSelectionListener(event -> { + if (!updating) { + updating = true; + int viewRow = parentsConceptTable.getSelectedRow(); + Global.conceptInfoAction.setEnabled(true); + int modelRow = parentsConceptTable.convertRowIndexToModel(viewRow); + Global.conceptInformationDialog.setConcept(parentConceptTableModel.getConcept(modelRow)); + updating = false; } }); - parentsConceptTable.hideColumn("Parents"); - parentsConceptTable.hideColumn("Children"); - parentsConceptTable.hideColumn("Valid start date"); - parentsConceptTable.hideColumn("Valid end date"); - parentsConceptTable.hideColumn("Invalid reason"); JScrollPane parentsPane = new JScrollPane(parentsConceptTable); parentsPane.setBorder(BorderFactory.createTitledBorder("Parent concepts")); parentsPane.setMinimumSize(new Dimension(500, 50)); parentsPane.setPreferredSize(new Dimension(500, 50)); c.gridy = 0; - c.weighty = 0.4; + c.weighty = 0.3; panel.add(parentsPane, c); + currentConceptTableModel = new ConceptTableModel(false); + currentConceptTable = hierarchyTableBuilder(currentConceptTableModel); + currentConceptTable.setRowSelectionAllowed(false); + JScrollPane currentConceptPane = new JScrollPane(currentConceptTable); + currentConceptPane.setBorder(BorderFactory.createTitledBorder("Current concept")); + currentConceptPane.setMinimumSize(new Dimension(500, 20)); + currentConceptPane.setPreferredSize(new Dimension(500, 20)); + c.gridy = 1; + c.weighty = 0.2; + panel.add(currentConceptPane, c); + childrenConceptTableModel = new ConceptTableModel(false); - childrenConceptTable = new UsagiTable(childrenConceptTableModel); - childrenConceptTable.setRowSorter(new TableRowSorter(childrenConceptTableModel)); - childrenConceptTable.setPreferredScrollableViewportSize(new Dimension(500, 45)); - childrenConceptTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + childrenConceptTable = hierarchyTableBuilder(childrenConceptTableModel); childrenConceptTable.setRowSelectionAllowed(true); - childrenConceptTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - childrenConceptTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent event) { - if (!updating) { - updating = true; - int viewRow = childrenConceptTable.getSelectedRow(); - Global.conceptInfoAction.setEnabled(true); - int modelRow = childrenConceptTable.convertRowIndexToModel(viewRow); - Global.conceptInformationDialog.setConcept(childrenConceptTableModel.getConcept(modelRow)); - updating = false; - } + childrenConceptTable.getSelectionModel().addListSelectionListener(event -> { + if (!updating) { + updating = true; + int viewRow = childrenConceptTable.getSelectedRow(); + Global.conceptInfoAction.setEnabled(true); + int modelRow = childrenConceptTable.convertRowIndexToModel(viewRow); + Global.conceptInformationDialog.setConcept(childrenConceptTableModel.getConcept(modelRow)); + updating = false; } }); - childrenConceptTable.hideColumn("Parents"); - childrenConceptTable.hideColumn("Children"); - childrenConceptTable.hideColumn("Valid start date"); - childrenConceptTable.hideColumn("Valid end date"); - childrenConceptTable.hideColumn("Invalid reason"); JScrollPane childrenPane = new JScrollPane(childrenConceptTable); childrenPane.setBorder(BorderFactory.createTitledBorder("Children concepts")); childrenPane.setMinimumSize(new Dimension(500, 50)); childrenPane.setPreferredSize(new Dimension(500, 50)); - c.gridy = 1; - c.weighty = 0.6; + c.gridy = 2; + c.weighty = 0.5; panel.add(childrenPane, c); return panel; } + private static UsagiTable hierarchyTableBuilder(ConceptTableModel tableModel) { + UsagiTable result = new UsagiTable(tableModel); + result.setRowSorter(new TableRowSorter<>(tableModel)); + result.setPreferredScrollableViewportSize(new Dimension(500, 45)); + result.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + result.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + result.hideColumn("Parents"); + result.hideColumn("Children"); + result.hideColumn("Valid start date"); + result.hideColumn("Valid end date"); + result.hideColumn("Invalid reason"); + return result; + } + private JScrollPane createInfoPanel() { area = new JTextArea(); area.setEditable(false); JScrollPane scrollPane = new JScrollPane(area); scrollPane.setBorder(BorderFactory.createTitledBorder("Concept information")); - scrollPane.setPreferredSize(new Dimension(600, 200)); + scrollPane.setPreferredSize(new Dimension(600, 150)); scrollPane.setMinimumSize(new Dimension(200, 100)); scrollPane.setAutoscrolls(true); return scrollPane; @@ -213,7 +219,6 @@ public void actionPerformed(ActionEvent e) { } }); - // replaceButton.setEnabled(false); buttonPanel.add(replaceButton); JButton addButton = new JButton("Add concept"); addButton.setToolTipText("Add selected concept"); @@ -224,7 +229,6 @@ public void actionPerformed(ActionEvent e) { } }); - // addButton.setEnabled(false); buttonPanel.add(addButton); return buttonPanel; } @@ -234,28 +238,16 @@ private Component createHeaderPanel() { panel.setBorder(BorderFactory.createEmptyBorder()); panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); conceptNameLabel = new JLabel("No concept selected"); - panel.add(conceptNameLabel); panel.add(Box.createHorizontalGlue()); + panel.add(conceptNameLabel); backButton = new JButton("<"); backButton.setToolTipText("Back to previous concept"); - backButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent arg0) { - goBack(); - } - }); + backButton.addActionListener(arg0 -> goBack()); backButton.setEnabled(false); panel.add(backButton); forwardButton = new JButton(">"); forwardButton.setToolTipText("Forward to next concept"); - forwardButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent arg0) { - goForward(); - } - }); + forwardButton.addActionListener(arg0 -> goForward()); forwardButton.setEnabled(false); panel.add(forwardButton); return panel; @@ -310,17 +302,19 @@ private void showConcept(Concept concept) { conceptInfo.append("\n" + concept.additionalInformation.replaceAll("\\\\n", "\n")); area.setText(conceptInfo.toString()); - List parents = new ArrayList(); + List parents = new ArrayList<>(); for (ParentChildRelationShip relationship : Global.dbEngine.getParentChildRelationshipsByChildConceptId(concept.conceptId)) parents.add(Global.dbEngine.getConcept(relationship.parentConceptId)); parentConceptTableModel.setConcepts(parents); - List children = new ArrayList(); + currentConceptTableModel.setConcepts(Collections.singletonList(concept)); + + List children = new ArrayList<>(); for (ParentChildRelationShip relationship : Global.dbEngine.getParentChildRelationshipsByParentConceptId(concept.conceptId)) children.add(Global.dbEngine.getConcept(relationship.childConceptId)); childrenConceptTableModel.setConcepts(children); - List sourceConcepts = new ArrayList(); + List sourceConcepts = new ArrayList<>(); for (MapsToRelationship relationship : Global.dbEngine.getMapsToRelationshipsByConceptId2(concept.conceptId)) sourceConcepts.add(Global.dbEngine.getConcept(relationship.conceptId1)); sourceConceptTableModel.setConcepts(sourceConcepts); From 704c9a7675f8dfe3b5577ad398e503469e26b395 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 18:49:56 +0100 Subject: [PATCH 06/17] remove concept information text area --- .../usagi/ui/ConceptInformationDialog.java | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java index 7c8a301..5718423 100644 --- a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java +++ b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java @@ -50,7 +50,6 @@ public class ConceptInformationDialog extends JFrame { private static final long serialVersionUID = -2112565437136224217L; - private JTextArea area; private JLabel conceptNameLabel; private JButton backButton; private JButton forwardButton; @@ -81,10 +80,8 @@ private Component createCenterPanel() { JPanel panel = new JPanel(); panel.setBorder(BorderFactory.createEmptyBorder()); panel.setLayout(new BorderLayout()); - JScrollPane infoPanel = createInfoPanel(); JTabbedPane tabPanel = createTabPanel(); - JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, infoPanel, tabPanel); - panel.add(splitPane, BorderLayout.CENTER); + panel.add(tabPanel, BorderLayout.CENTER); return panel; } @@ -125,7 +122,7 @@ private Component createHierarchyPanel() { parentConceptTableModel = new ConceptTableModel(false); parentsConceptTable = hierarchyTableBuilder(parentConceptTableModel); - currentConceptTable.setRowSelectionAllowed(true); + parentsConceptTable.setRowSelectionAllowed(true); parentsConceptTable.getSelectionModel().addListSelectionListener(event -> { if (!updating) { updating = true; @@ -194,17 +191,6 @@ private static UsagiTable hierarchyTableBuilder(ConceptTableModel tableModel) { return result; } - private JScrollPane createInfoPanel() { - area = new JTextArea(); - area.setEditable(false); - JScrollPane scrollPane = new JScrollPane(area); - scrollPane.setBorder(BorderFactory.createTitledBorder("Concept information")); - scrollPane.setPreferredSize(new Dimension(600, 150)); - scrollPane.setMinimumSize(new Dimension(200, 100)); - scrollPane.setAutoscrolls(true); - return scrollPane; - } - private JPanel createButtonPanel() { JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); @@ -289,19 +275,6 @@ private void showConcept(Concept concept) { name = name.substring(0, 80) + "..."; conceptNameLabel.setText(name + " (" + concept.conceptId + ")"); - StringBuilder conceptInfo = new StringBuilder(); - conceptInfo.append("Concept name: " + concept.conceptName + "\n"); - conceptInfo.append("Domain ID: " + concept.domainId + "\n"); - conceptInfo.append("Concept class ID: " + concept.conceptClassId + "\n"); - conceptInfo.append("Vocabulary ID: " + concept.vocabularyId + "\n"); - conceptInfo.append("Concept ID: " + concept.conceptId + "\n"); - conceptInfo.append("Concept code: " + concept.conceptCode + "\n"); - conceptInfo.append("Invalid reason: " + concept.invalidReason + "\n"); - conceptInfo.append("Standard concept: " + concept.standardConcept + "\n"); - if (concept.additionalInformation != null) - conceptInfo.append("\n" + concept.additionalInformation.replaceAll("\\\\n", "\n")); - area.setText(conceptInfo.toString()); - List parents = new ArrayList<>(); for (ParentChildRelationShip relationship : Global.dbEngine.getParentChildRelationshipsByChildConceptId(concept.conceptId)) parents.add(Global.dbEngine.getConcept(relationship.parentConceptId)); From 04b0406cd780ecf257a5aef905857a80f62185b8 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 18:56:49 +0100 Subject: [PATCH 07/17] further refactoring --- .../usagi/ui/ConceptInformationDialog.java | 57 ++++++------------- 1 file changed, 18 insertions(+), 39 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java index 5718423..1976f81 100644 --- a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java +++ b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java @@ -20,8 +20,6 @@ import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -34,13 +32,9 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; -import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTable; -import javax.swing.JTextArea; import javax.swing.ListSelectionModel; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import javax.swing.table.TableRowSorter; import org.ohdsi.usagi.Concept; @@ -56,12 +50,10 @@ public class ConceptInformationDialog extends JFrame { private ConceptTableModel parentConceptTableModel; private UsagiTable parentsConceptTable; private ConceptTableModel currentConceptTableModel; - private UsagiTable currentConceptTable; private ConceptTableModel childrenConceptTableModel; private UsagiTable childrenConceptTable; private ConceptTableModel sourceConceptTableModel; - private UsagiTable sourceConceptTable; - private List history = new ArrayList(); + private List history = new ArrayList<>(); private int historyCursor = -1; private boolean updating = false; @@ -94,16 +86,7 @@ private JTabbedPane createTabPanel() { private Component createSourceConceptPanel() { sourceConceptTableModel = new ConceptTableModel(false); - sourceConceptTable = new UsagiTable(sourceConceptTableModel); - sourceConceptTable.setPreferredScrollableViewportSize(new Dimension(500, 45)); - sourceConceptTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - sourceConceptTable.setRowSelectionAllowed(false); - sourceConceptTable.setRowSorter(new TableRowSorter<>(sourceConceptTableModel)); - sourceConceptTable.hideColumn("Parents"); - sourceConceptTable.hideColumn("Children"); - sourceConceptTable.hideColumn("Valid start date"); - sourceConceptTable.hideColumn("Valid end date"); - sourceConceptTable.hideColumn("Invalid reason"); + UsagiTable sourceConceptTable = buildConceptTable(sourceConceptTableModel, false); JScrollPane sourcePane = new JScrollPane(sourceConceptTable); sourcePane.setBorder(BorderFactory.createTitledBorder("Source concepts")); @@ -121,8 +104,7 @@ private Component createHierarchyPanel() { c.weightx = 1; parentConceptTableModel = new ConceptTableModel(false); - parentsConceptTable = hierarchyTableBuilder(parentConceptTableModel); - parentsConceptTable.setRowSelectionAllowed(true); + parentsConceptTable = buildConceptTable(parentConceptTableModel, true); parentsConceptTable.getSelectionModel().addListSelectionListener(event -> { if (!updating) { updating = true; @@ -143,8 +125,7 @@ private Component createHierarchyPanel() { panel.add(parentsPane, c); currentConceptTableModel = new ConceptTableModel(false); - currentConceptTable = hierarchyTableBuilder(currentConceptTableModel); - currentConceptTable.setRowSelectionAllowed(false); + UsagiTable currentConceptTable = buildConceptTable(currentConceptTableModel, false); JScrollPane currentConceptPane = new JScrollPane(currentConceptTable); currentConceptPane.setBorder(BorderFactory.createTitledBorder("Current concept")); currentConceptPane.setMinimumSize(new Dimension(500, 20)); @@ -154,8 +135,7 @@ private Component createHierarchyPanel() { panel.add(currentConceptPane, c); childrenConceptTableModel = new ConceptTableModel(false); - childrenConceptTable = hierarchyTableBuilder(childrenConceptTableModel); - childrenConceptTable.setRowSelectionAllowed(true); + childrenConceptTable = buildConceptTable(childrenConceptTableModel, true); childrenConceptTable.getSelectionModel().addListSelectionListener(event -> { if (!updating) { updating = true; @@ -177,17 +157,22 @@ private Component createHierarchyPanel() { return panel; } - private static UsagiTable hierarchyTableBuilder(ConceptTableModel tableModel) { + private static UsagiTable buildConceptTable(ConceptTableModel tableModel, boolean rowSelectionAllowed) { UsagiTable result = new UsagiTable(tableModel); result.setRowSorter(new TableRowSorter<>(tableModel)); result.setPreferredScrollableViewportSize(new Dimension(500, 45)); result.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - result.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); result.hideColumn("Parents"); result.hideColumn("Children"); result.hideColumn("Valid start date"); result.hideColumn("Valid end date"); result.hideColumn("Invalid reason"); + + result.setRowSelectionAllowed(rowSelectionAllowed); + if (rowSelectionAllowed) { + result.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + } + return result; } @@ -198,22 +183,16 @@ private JPanel createButtonPanel() { JButton replaceButton = new JButton("Replace concept"); replaceButton.setToolTipText("Replace selected concept"); - replaceButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Global.mappingDetailPanel.replaceConcepts(history.get(historyCursor)); - Global.frame.requestFocus(); - } - + replaceButton.addActionListener(e -> { + Global.mappingDetailPanel.replaceConcepts(history.get(historyCursor)); + Global.frame.requestFocus(); }); buttonPanel.add(replaceButton); JButton addButton = new JButton("Add concept"); addButton.setToolTipText("Add selected concept"); - addButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Global.mappingDetailPanel.addConcept(history.get(historyCursor)); - Global.frame.requestFocus(); - } - + addButton.addActionListener(e -> { + Global.mappingDetailPanel.addConcept(history.get(historyCursor)); + Global.frame.requestFocus(); }); buttonPanel.add(addButton); return buttonPanel; From dd5edb8515ce5edc38b76ebecf2a70e8d7012236 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 20:12:27 +0100 Subject: [PATCH 08/17] only lookup concept information if window is visible --- .../usagi/ui/ConceptInformationDialog.java | 21 +++++++++++++++---- .../ohdsi/usagi/ui/MappingDetailPanel.java | 4 ++-- src/org/ohdsi/usagi/ui/MappingTablePanel.java | 3 +-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java index 1976f81..d3182f8 100644 --- a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java +++ b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java @@ -44,6 +44,7 @@ public class ConceptInformationDialog extends JFrame { private static final long serialVersionUID = -2112565437136224217L; + private Concept activeConcept; private JLabel conceptNameLabel; private JButton backButton; private JButton forwardButton; @@ -111,7 +112,7 @@ private Component createHierarchyPanel() { int viewRow = parentsConceptTable.getSelectedRow(); Global.conceptInfoAction.setEnabled(true); int modelRow = parentsConceptTable.convertRowIndexToModel(viewRow); - Global.conceptInformationDialog.setConcept(parentConceptTableModel.getConcept(modelRow)); + Global.conceptInformationDialog.setActiveConcept(parentConceptTableModel.getConcept(modelRow)); updating = false; } }); @@ -142,7 +143,7 @@ private Component createHierarchyPanel() { int viewRow = childrenConceptTable.getSelectedRow(); Global.conceptInfoAction.setEnabled(true); int modelRow = childrenConceptTable.convertRowIndexToModel(viewRow); - Global.conceptInformationDialog.setConcept(childrenConceptTableModel.getConcept(modelRow)); + Global.conceptInformationDialog.setActiveConcept(childrenConceptTableModel.getConcept(modelRow)); updating = false; } }); @@ -236,7 +237,10 @@ private void goForward() { showConcept(concept); } - public void setConcept(Concept concept) { + public void setActiveConcept(Concept concept) { + this.activeConcept = concept; + + // Keep track of active concept history if (historyCursor < 0 || history.get(historyCursor).conceptId != concept.conceptId) { if (historyCursor < history.size() - 1) history = history.subList(0, historyCursor + 1); @@ -244,8 +248,17 @@ public void setConcept(Concept concept) { history.add(concept); backButton.setEnabled(historyCursor > 0); forwardButton.setEnabled(false); - showConcept(concept); } + + if (this.isVisible()) { + showConcept(activeConcept); + } + } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + this.showConcept(activeConcept); } private void showConcept(Concept concept) { diff --git a/src/org/ohdsi/usagi/ui/MappingDetailPanel.java b/src/org/ohdsi/usagi/ui/MappingDetailPanel.java index c42b06f..dd40068 100644 --- a/src/org/ohdsi/usagi/ui/MappingDetailPanel.java +++ b/src/org/ohdsi/usagi/ui/MappingDetailPanel.java @@ -186,7 +186,7 @@ private Component createSearchResultsPanel() { replaceButton.setEnabled(true); int modelRow = searchTable.convertRowIndexToModel(viewRow); Global.conceptInfoAction.setEnabled(true); - Global.conceptInformationDialog.setConcept(searchTableModel.getConcept(modelRow)); + Global.conceptInformationDialog.setActiveConcept(searchTableModel.getConcept(modelRow)); Global.athenaAction.setEnabled(true); Global.athenaAction.setConcept(searchTableModel.getConcept(modelRow)); Global.googleSearchAction.setEnabled(false); @@ -330,7 +330,7 @@ private JPanel createTargetConceptsPanel() { MappingTarget mappingTarget = targetConceptTableModel.getMappingTarget(modelRow); typesChooser.setSelectedItem(mappingTarget.getMappingType()); Global.conceptInfoAction.setEnabled(true); - Global.conceptInformationDialog.setConcept(mappingTarget.getConcept()); + Global.conceptInformationDialog.setActiveConcept(mappingTarget.getConcept()); Global.athenaAction.setEnabled(true); Global.athenaAction.setConcept(mappingTarget.getConcept()); Global.googleSearchAction.setEnabled(false); diff --git a/src/org/ohdsi/usagi/ui/MappingTablePanel.java b/src/org/ohdsi/usagi/ui/MappingTablePanel.java index d69c331..9992477 100644 --- a/src/org/ohdsi/usagi/ui/MappingTablePanel.java +++ b/src/org/ohdsi/usagi/ui/MappingTablePanel.java @@ -31,7 +31,6 @@ import javax.swing.table.AbstractTableModel; import javax.swing.table.TableRowSorter; -import org.apache.xmlbeans.impl.xb.ltgfmt.Code; import org.ohdsi.usagi.CodeMapping; import org.ohdsi.usagi.CodeMapping.MappingStatus; import org.ohdsi.usagi.Concept; @@ -73,7 +72,7 @@ public MappingTablePanel() { if (tableModel.getCodeMapping(primaryModelRow).getTargetConcepts().size() > 0) { Concept firstConcept = tableModel.getCodeMapping(primaryModelRow).getTargetConcepts().get(0).getConcept(); Global.conceptInfoAction.setEnabled(true); - Global.conceptInformationDialog.setConcept(firstConcept); + Global.conceptInformationDialog.setActiveConcept(firstConcept); Global.athenaAction.setEnabled(true); Global.athenaAction.setConcept(firstConcept); } From 98504ff37f801d7b122a95d554e782b42e8faf80 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 20:38:35 +0100 Subject: [PATCH 09/17] add synonyms to concept information --- src/org/ohdsi/usagi/UsagiSearchEngine.java | 21 +++++++++++++ .../usagi/ui/ConceptInformationDialog.java | 31 ++++++++++++------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/org/ohdsi/usagi/UsagiSearchEngine.java b/src/org/ohdsi/usagi/UsagiSearchEngine.java index fd0c55f..61636d1 100644 --- a/src/org/ohdsi/usagi/UsagiSearchEngine.java +++ b/src/org/ohdsi/usagi/UsagiSearchEngine.java @@ -278,6 +278,27 @@ public int getTermCount() { } + public List searchTermsByConceptId(int conceptID) { + List result = new ArrayList<>(); + try { + QueryParser keywordsQueryParser = new QueryParser(Version.LUCENE_4_9, "CONCEPT_ID", new KeywordAnalyzer()); + Query conceptIdQuery = keywordsQueryParser.parse("\"" + Integer.toString(conceptID) + "\""); + BooleanQuery booleanQuery = new BooleanQuery(); + booleanQuery.add(conceptIdQuery, Occur.MUST); + TopDocs topDocs = searcher.search(booleanQuery, 100); + for (ScoreDoc scoreDoc : topDocs.scoreDocs) { + Document document = reader.document(scoreDoc.doc); + String term = document.get("TERM"); + String termType = document.get("TERM_TYPE"); + result.add(termType + " - " + term); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + e.printStackTrace(); + } + return result; + } + public List search(String searchTerm, boolean useMlt, Collection filterConceptIds, Vector filterDomains, Vector filterConceptClasses, Vector filterVocabularies, boolean filterStandard, boolean includeSourceConcepts) { List results = new ArrayList(); diff --git a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java index d3182f8..de43abe 100644 --- a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java +++ b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java @@ -24,17 +24,7 @@ import java.util.Collections; import java.util.List; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.JTable; -import javax.swing.ListSelectionModel; +import javax.swing.*; import javax.swing.table.TableRowSorter; import org.ohdsi.usagi.Concept; @@ -54,6 +44,7 @@ public class ConceptInformationDialog extends JFrame { private ConceptTableModel childrenConceptTableModel; private UsagiTable childrenConceptTable; private ConceptTableModel sourceConceptTableModel; + private JTextArea synonymArea; private List history = new ArrayList<>(); private int historyCursor = -1; private boolean updating = false; @@ -82,6 +73,7 @@ private JTabbedPane createTabPanel() { JTabbedPane tabbedPane = new JTabbedPane(); tabbedPane.addTab("Hierarchy", createHierarchyPanel()); tabbedPane.addTab("Source concepts", createSourceConceptPanel()); + tabbedPane.addTab("Synonyms", createSynonymsPanel()); return tabbedPane; } @@ -177,6 +169,16 @@ private static UsagiTable buildConceptTable(ConceptTableModel tableModel, boolea return result; } + private Component createSynonymsPanel() { + synonymArea = new JTextArea(); + synonymArea.setEditable(false); + JScrollPane synonymPane = new JScrollPane(synonymArea); + synonymPane.setBorder(BorderFactory.createTitledBorder("Synonyms")); + synonymPane.setMinimumSize(new Dimension(500, 50)); + synonymPane.setPreferredSize(new Dimension(500, 50)); + return synonymPane; + } + private JPanel createButtonPanel() { JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); @@ -283,5 +285,12 @@ private void showConcept(Concept concept) { for (MapsToRelationship relationship : Global.dbEngine.getMapsToRelationshipsByConceptId2(concept.conceptId)) sourceConcepts.add(Global.dbEngine.getConcept(relationship.conceptId1)); sourceConceptTableModel.setConcepts(sourceConcepts); + + List synonyms = Global.usagiSearchEngine.searchTermsByConceptId(concept.conceptId); + StringBuilder text = new StringBuilder(); + for (String synonym : synonyms) { + text.append(synonym + "\n"); + } + synonymArea.setText(text.toString()); } } From 59cbce929650d2b2dfd4aaaa7366452a52ef5fe7 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Fri, 12 Mar 2021 20:59:42 +0100 Subject: [PATCH 10/17] split synonyms in concept and source synonyms --- src/org/ohdsi/usagi/UsagiSearchEngine.java | 58 +++++++++++-------- .../usagi/ui/ConceptInformationDialog.java | 57 +++++++++++++----- 2 files changed, 79 insertions(+), 36 deletions(-) diff --git a/src/org/ohdsi/usagi/UsagiSearchEngine.java b/src/org/ohdsi/usagi/UsagiSearchEngine.java index 61636d1..84892f0 100644 --- a/src/org/ohdsi/usagi/UsagiSearchEngine.java +++ b/src/org/ohdsi/usagi/UsagiSearchEngine.java @@ -278,29 +278,8 @@ public int getTermCount() { } - public List searchTermsByConceptId(int conceptID) { - List result = new ArrayList<>(); - try { - QueryParser keywordsQueryParser = new QueryParser(Version.LUCENE_4_9, "CONCEPT_ID", new KeywordAnalyzer()); - Query conceptIdQuery = keywordsQueryParser.parse("\"" + Integer.toString(conceptID) + "\""); - BooleanQuery booleanQuery = new BooleanQuery(); - booleanQuery.add(conceptIdQuery, Occur.MUST); - TopDocs topDocs = searcher.search(booleanQuery, 100); - for (ScoreDoc scoreDoc : topDocs.scoreDocs) { - Document document = reader.document(scoreDoc.doc); - String term = document.get("TERM"); - String termType = document.get("TERM_TYPE"); - result.add(termType + " - " + term); - } - } catch (Exception e) { - System.err.println(e.getMessage()); - e.printStackTrace(); - } - return result; - } - public List search(String searchTerm, boolean useMlt, Collection filterConceptIds, Vector filterDomains, Vector filterConceptClasses, - Vector filterVocabularies, boolean filterStandard, boolean includeSourceConcepts) { + Vector filterVocabularies, boolean filterStandard, boolean includeSourceConcepts) { List results = new ArrayList(); try { Query query; @@ -427,7 +406,7 @@ else if (arg1.term.toLowerCase().equals(arg1.concept.conceptName.toLowerCase())) /** * Lucene's matching score does some weird things: it is not normalized (the value can be greater than 1), and not all tokens are included in the * computation. For that reason, we're recomputing the matching score as plain TF*IDF cosine matching here. - * + * * @param scoreDocs * The array of documents scored by Lucene * @param query @@ -459,6 +438,39 @@ public int compare(ScoreDoc arg0, ScoreDoc arg1) { } } + public List searchConceptSynonymsByConceptId(int conceptId) { + return searchTermsByConceptId(conceptId, CONCEPT_TERM); + } + + public List searchSourceSynonymsByConceptId(int conceptId) { + return searchTermsByConceptId(conceptId, SOURCE_TERM); + } + + private List searchTermsByConceptId(int conceptId, String termType) { + List result = new ArrayList<>(); + try { + QueryParser keywordsQueryParser = new QueryParser(Version.LUCENE_4_9, "CONCEPT_ID", new KeywordAnalyzer()); + Query conceptIdQuery = keywordsQueryParser.parse(String.valueOf(conceptId)); + BooleanQuery booleanQuery = new BooleanQuery(); + booleanQuery.add(conceptIdQuery, Occur.MUST); + + QueryParser termTypeQueryParser = new QueryParser(Version.LUCENE_4_9, "TERM_TYPE", new KeywordAnalyzer()); + Query termTypeQuery = termTypeQueryParser.parse(termType); + booleanQuery.add(termTypeQuery, Occur.MUST); + + TopDocs topDocs = searcher.search(booleanQuery, 100); + for (ScoreDoc scoreDoc : topDocs.scoreDocs) { + Document document = reader.document(scoreDoc.doc); + String term = document.get("TERM"); + result.add(term); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + e.printStackTrace(); + } + return result; + } + public static class ScoredConcept { public float matchScore; public Concept concept; diff --git a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java index de43abe..e7d6fa6 100644 --- a/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java +++ b/src/org/ohdsi/usagi/ui/ConceptInformationDialog.java @@ -44,7 +44,8 @@ public class ConceptInformationDialog extends JFrame { private ConceptTableModel childrenConceptTableModel; private UsagiTable childrenConceptTable; private ConceptTableModel sourceConceptTableModel; - private JTextArea synonymArea; + private JTextArea conceptSynonymArea; + private JTextArea sourceSynonymArea; private List history = new ArrayList<>(); private int historyCursor = -1; private boolean updating = false; @@ -170,13 +171,36 @@ private static UsagiTable buildConceptTable(ConceptTableModel tableModel, boolea } private Component createSynonymsPanel() { - synonymArea = new JTextArea(); - synonymArea.setEditable(false); - JScrollPane synonymPane = new JScrollPane(synonymArea); - synonymPane.setBorder(BorderFactory.createTitledBorder("Synonyms")); - synonymPane.setMinimumSize(new Dimension(500, 50)); - synonymPane.setPreferredSize(new Dimension(500, 50)); - return synonymPane; + JPanel panel = new JPanel(); + panel.setBorder(BorderFactory.createEmptyBorder()); + panel.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + + conceptSynonymArea = new JTextArea(); + conceptSynonymArea.setEditable(false); + + JScrollPane conceptSynonymPane = new JScrollPane(conceptSynonymArea); + conceptSynonymPane.setBorder(BorderFactory.createTitledBorder("Concept Synonyms")); + conceptSynonymPane.setMinimumSize(new Dimension(500, 50)); + conceptSynonymPane.setPreferredSize(new Dimension(500, 50)); + c.gridy = 0; + c.weighty = 0.5; + panel.add(conceptSynonymPane, c); + + sourceSynonymArea = new JTextArea(); + sourceSynonymArea.setEditable(false); + + JScrollPane sourceSynonymPane = new JScrollPane(sourceSynonymArea); + sourceSynonymPane.setBorder(BorderFactory.createTitledBorder("Source Synonyms")); + sourceSynonymPane.setMinimumSize(new Dimension(500, 50)); + sourceSynonymPane.setPreferredSize(new Dimension(500, 50)); + c.gridy = 1; + c.weighty = 0.5; + panel.add(sourceSynonymPane, c); + + return panel; } private JPanel createButtonPanel() { @@ -286,11 +310,18 @@ private void showConcept(Concept concept) { sourceConcepts.add(Global.dbEngine.getConcept(relationship.conceptId1)); sourceConceptTableModel.setConcepts(sourceConcepts); - List synonyms = Global.usagiSearchEngine.searchTermsByConceptId(concept.conceptId); - StringBuilder text = new StringBuilder(); - for (String synonym : synonyms) { - text.append(synonym + "\n"); + List conceptSynonyms = Global.usagiSearchEngine.searchConceptSynonymsByConceptId(concept.conceptId); + StringBuilder conceptSynonymsText = new StringBuilder(); + for (String synonym : conceptSynonyms) { + conceptSynonymsText.append(synonym).append("\n"); + } + conceptSynonymArea.setText(conceptSynonymsText.toString()); + + List sourceSynonyms = Global.usagiSearchEngine.searchSourceSynonymsByConceptId(concept.conceptId); + StringBuilder sourceSynonymsText = new StringBuilder(); + for (String synonym : sourceSynonyms) { + sourceSynonymsText.append(synonym).append("\n"); } - synonymArea.setText(text.toString()); + sourceSynonymArea.setText(sourceSynonymsText.toString()); } } From eee31563e81f629309c86e218520eff5faa23ac5 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Mon, 15 Mar 2021 00:19:08 +0100 Subject: [PATCH 11/17] new review status dialog --- src/org/ohdsi/usagi/ui/Global.java | 1 + .../ohdsi/usagi/ui/ShowReviewStatsDialog.java | 133 ++++++++++++++++++ src/org/ohdsi/usagi/ui/UsagiMain.java | 1 + src/org/ohdsi/usagi/ui/UsagiMenubar.java | 1 + .../ui/actions/ShowReviewStatsAction.java | 42 ++++++ 5 files changed, 178 insertions(+) create mode 100644 src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java create mode 100644 src/org/ohdsi/usagi/ui/actions/ShowReviewStatsAction.java diff --git a/src/org/ohdsi/usagi/ui/Global.java b/src/org/ohdsi/usagi/ui/Global.java index be488b8..9c70139 100644 --- a/src/org/ohdsi/usagi/ui/Global.java +++ b/src/org/ohdsi/usagi/ui/Global.java @@ -58,6 +58,7 @@ public class Global { public static Vector vocabularyIds; public static Vector domainIds; public static ShowStatsAction showStatsAction; + public static ShowReviewStatsAction showReviewStatsAction; public static String author; } diff --git a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java new file mode 100644 index 0000000..8522af3 --- /dev/null +++ b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright 2021 Observational Health Data Sciences and Informatics & The Hyve + * + * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +package org.ohdsi.usagi.ui; + +import org.ohdsi.usagi.CodeMapping; +import org.ohdsi.utilities.collections.Pair; + +import javax.swing.*; +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +public class ShowReviewStatsDialog extends JDialog { + + private static final long serialVersionUID = 2028328868610404663L; + + public ShowReviewStatsDialog() { + Font headerFont = new Font("Arial", Font.BOLD,12); + + setTitle("Review statistics"); + setLayout(new GridBagLayout()); + + GridBagConstraints g = new GridBagConstraints(); + g.fill = GridBagConstraints.BOTH; + g.ipadx = 10; + g.ipady = 10; + + g.gridx = 0; + g.gridy = 0; + add(new JLabel(String.format("Number of source codes: %d", Global.mapping.size())), g); + + g.gridx = 0; + g.gridy++; + JLabel l = new JLabel("By equivalence status:"); + l.setFont(headerFont); + add(l, g); + + Map reviewResults = new HashMap<>(); + for (CodeMapping codeMapping : Global.mapping) { + reviewResults.putIfAbsent(codeMapping.getEquivalence(), 0); + Integer c = reviewResults.get(codeMapping.getEquivalence()); + reviewResults.put(codeMapping.getEquivalence(), ++c); + } + + reviewResults.forEach((key, value) -> { + g.gridx = 0; + g.gridy++; + add(new JLabel(String.format("%s - %d", key, value)), g); + }); + + g.gridx = 0; + g.gridy++; + l = new JLabel("By reviewer:"); + l.setFont(headerFont); + add(l, g); + + Map> reviewerResults = new HashMap<>(); + for (CodeMapping codeMapping : Global.mapping) { + reviewerResults.putIfAbsent(codeMapping.getAssignedReviewer(), new Pair<>(0,0)); + Pair c = reviewerResults.get(codeMapping.getAssignedReviewer()); + Integer nApproved = c.getItem1(); + if (codeMapping.getMappingStatus() == CodeMapping.MappingStatus.APPROVED) { + c.setItem1(++nApproved); + } + Integer nTotal = c.getItem2(); + c.setItem2(++nTotal); + } + + reviewerResults.forEach((key, value) -> { + g.gridx = 0; + g.gridy++; + add(new JLabel(String.format("%s - %d/%d", key, value.getItem1(), value.getItem2())), g); + }); + + g.gridx = 0; + g.gridy++; + l = new JLabel("By number of targets:"); + l.setFont(headerFont); + add(l, g); + + Map oneToManyResults = new HashMap<>(); + for (CodeMapping codeMapping : Global.mapping) { + Integer nTargets = codeMapping.getTargetConcepts().size(); + oneToManyResults.putIfAbsent(nTargets, 0); + Integer c = oneToManyResults.get(nTargets); + oneToManyResults.put(nTargets, ++c); + } + + oneToManyResults.forEach((key, value) -> { + g.gridx = 0; + g.gridy++; + add(new JLabel(String.format("%d - %d", key, value)), g); + }); + + g.gridx = 0; + g.gridy++; + g.gridwidth = 2; + + JPanel buttonPanel = new JPanel(); + + buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); + buttonPanel.add(Box.createHorizontalGlue()); + + JButton okButton = new JButton("Ok"); + okButton.addActionListener(arg0 -> close()); + buttonPanel.add(okButton); + buttonPanel.add(Box.createHorizontalGlue()); + + add(buttonPanel, g); + + setModal(true); + setResizable(false); + pack(); + + } + + private void close() { + setVisible(false); + } +} diff --git a/src/org/ohdsi/usagi/ui/UsagiMain.java b/src/org/ohdsi/usagi/ui/UsagiMain.java index 108cc65..bd82fc6 100644 --- a/src/org/ohdsi/usagi/ui/UsagiMain.java +++ b/src/org/ohdsi/usagi/ui/UsagiMain.java @@ -85,6 +85,7 @@ public UsagiMain(String[] args) { Global.athenaAction = new AthenaAction(); Global.googleSearchAction = new GoogleSearchAction(); Global.showStatsAction = new ShowStatsAction(); + Global.showReviewStatsAction = new ShowReviewStatsAction(); Global.aboutAction = new AboutAction(); Global.rebuildIndexAction = new RebuildIndexAction(); Global.exitAction = new ExitAction(); diff --git a/src/org/ohdsi/usagi/ui/UsagiMenubar.java b/src/org/ohdsi/usagi/ui/UsagiMenubar.java index f36ce04..ea03e6f 100644 --- a/src/org/ohdsi/usagi/ui/UsagiMenubar.java +++ b/src/org/ohdsi/usagi/ui/UsagiMenubar.java @@ -59,6 +59,7 @@ public UsagiMenubar() { helpMenu.add(Global.rebuildIndexAction); helpMenu.add(Global.showStatsAction); + helpMenu.add(Global.showReviewStatsAction); helpMenu.add(Global.aboutAction); } diff --git a/src/org/ohdsi/usagi/ui/actions/ShowReviewStatsAction.java b/src/org/ohdsi/usagi/ui/actions/ShowReviewStatsAction.java new file mode 100644 index 0000000..bacba30 --- /dev/null +++ b/src/org/ohdsi/usagi/ui/actions/ShowReviewStatsAction.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright 2021 Observational Health Data Sciences and Informatics & The Hyve + * + * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +package org.ohdsi.usagi.ui.actions; + +import org.ohdsi.usagi.ui.Global; +import org.ohdsi.usagi.ui.ShowReviewStatsDialog; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class ShowReviewStatsAction extends AbstractAction { + + private static final long serialVersionUID = -5823000156280268511L; + + public ShowReviewStatsAction() { + putValue(Action.NAME, "Show code review statistics"); + putValue(Action.SHORT_DESCRIPTION, "Show review stats"); + putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_MASK)); + } + + @Override + public void actionPerformed(ActionEvent arg0) { + ShowReviewStatsDialog dialog = new ShowReviewStatsDialog(); + dialog.setLocationRelativeTo(Global.frame); + dialog.setVisible(true); + } +} From cdc115fb910faf1717b12d4277501488d73ed32d Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Mon, 15 Mar 2021 09:44:07 +0100 Subject: [PATCH 12/17] review stats on only selected codes --- src/org/ohdsi/usagi/ui/MappingTablePanel.java | 10 +++++++++- .../ohdsi/usagi/ui/ShowReviewStatsDialog.java | 17 +++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/MappingTablePanel.java b/src/org/ohdsi/usagi/ui/MappingTablePanel.java index d69c331..ef99ad6 100644 --- a/src/org/ohdsi/usagi/ui/MappingTablePanel.java +++ b/src/org/ohdsi/usagi/ui/MappingTablePanel.java @@ -31,7 +31,6 @@ import javax.swing.table.AbstractTableModel; import javax.swing.table.TableRowSorter; -import org.apache.xmlbeans.impl.xb.ltgfmt.Code; import org.ohdsi.usagi.CodeMapping; import org.ohdsi.usagi.CodeMapping.MappingStatus; import org.ohdsi.usagi.Concept; @@ -319,6 +318,15 @@ public void clearSelected() { fireUpdateEventAll(MULTI_UPDATE_EVENT); } + public List getSelectedCodeMappings() { + List selectedCodeMappings = new ArrayList<>(); + for (int viewRow : table.getSelectedRows()) { + int modelRow = table.convertRowIndexToModel(viewRow); + selectedCodeMappings.add(tableModel.getCodeMapping(modelRow)); + } + return selectedCodeMappings; + } + public void assignReviewersRandomly(String[] reviewers) { // Randomly assign code mappings to given reviewers ThreadLocalRandom randomGenerator = ThreadLocalRandom.current(); diff --git a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java index 8522af3..d9ede1e 100644 --- a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java +++ b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java @@ -21,6 +21,7 @@ import javax.swing.*; import java.awt.*; import java.util.HashMap; +import java.util.List; import java.util.Map; public class ShowReviewStatsDialog extends JDialog { @@ -30,6 +31,14 @@ public class ShowReviewStatsDialog extends JDialog { public ShowReviewStatsDialog() { Font headerFont = new Font("Arial", Font.BOLD,12); + java.util.List selectedCodeMappings = Global.mappingTablePanel.getSelectedCodeMappings(); + List codeMappings; + if (selectedCodeMappings.size() > 1) { + codeMappings = selectedCodeMappings; + } else { + codeMappings = Global.mapping; + } + setTitle("Review statistics"); setLayout(new GridBagLayout()); @@ -40,7 +49,7 @@ public ShowReviewStatsDialog() { g.gridx = 0; g.gridy = 0; - add(new JLabel(String.format("Number of source codes: %d", Global.mapping.size())), g); + add(new JLabel(String.format("Number of (selected) source codes: %d", codeMappings.size())), g); g.gridx = 0; g.gridy++; @@ -49,7 +58,7 @@ public ShowReviewStatsDialog() { add(l, g); Map reviewResults = new HashMap<>(); - for (CodeMapping codeMapping : Global.mapping) { + for (CodeMapping codeMapping : codeMappings) { reviewResults.putIfAbsent(codeMapping.getEquivalence(), 0); Integer c = reviewResults.get(codeMapping.getEquivalence()); reviewResults.put(codeMapping.getEquivalence(), ++c); @@ -68,7 +77,7 @@ public ShowReviewStatsDialog() { add(l, g); Map> reviewerResults = new HashMap<>(); - for (CodeMapping codeMapping : Global.mapping) { + for (CodeMapping codeMapping : codeMappings) { reviewerResults.putIfAbsent(codeMapping.getAssignedReviewer(), new Pair<>(0,0)); Pair c = reviewerResults.get(codeMapping.getAssignedReviewer()); Integer nApproved = c.getItem1(); @@ -92,7 +101,7 @@ public ShowReviewStatsDialog() { add(l, g); Map oneToManyResults = new HashMap<>(); - for (CodeMapping codeMapping : Global.mapping) { + for (CodeMapping codeMapping : codeMappings) { Integer nTargets = codeMapping.getTargetConcepts().size(); oneToManyResults.putIfAbsent(nTargets, 0); Integer c = oneToManyResults.get(nTargets); From 1834368ffaa15752f12efe87fab2fa1980aaac10 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Mon, 15 Mar 2021 12:02:39 +0100 Subject: [PATCH 13/17] add mapping status stats --- .../ohdsi/usagi/ui/ShowReviewStatsDialog.java | 55 +++++++++++++------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java index d9ede1e..ccdd642 100644 --- a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java +++ b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java @@ -44,42 +44,64 @@ public ShowReviewStatsDialog() { GridBagConstraints g = new GridBagConstraints(); g.fill = GridBagConstraints.BOTH; - g.ipadx = 10; + g.ipadx = 50; g.ipady = 10; g.gridx = 0; g.gridy = 0; add(new JLabel(String.format("Number of (selected) source codes: %d", codeMappings.size())), g); + // Mapping status g.gridx = 0; g.gridy++; - JLabel l = new JLabel("By equivalence status:"); + JLabel l = new JLabel("By mapping status:"); l.setFont(headerFont); add(l, g); - Map reviewResults = new HashMap<>(); + Map mappingStats = new HashMap<>(); for (CodeMapping codeMapping : codeMappings) { - reviewResults.putIfAbsent(codeMapping.getEquivalence(), 0); - Integer c = reviewResults.get(codeMapping.getEquivalence()); - reviewResults.put(codeMapping.getEquivalence(), ++c); + mappingStats.putIfAbsent(codeMapping.getMappingStatus(), 0); + Integer c = mappingStats.get(codeMapping.getMappingStatus()); + mappingStats.put(codeMapping.getMappingStatus(), ++c); } - reviewResults.forEach((key, value) -> { + mappingStats.forEach((key, value) -> { g.gridx = 0; g.gridy++; add(new JLabel(String.format("%s - %d", key, value)), g); }); + // Equivalence status + g.gridx = 0; + g.gridy++; + l = new JLabel("By equivalence status:"); + l.setFont(headerFont); + add(l, g); + + Map equivalenceStats = new HashMap<>(); + for (CodeMapping codeMapping : codeMappings) { + equivalenceStats.putIfAbsent(codeMapping.getEquivalence(), 0); + Integer c = equivalenceStats.get(codeMapping.getEquivalence()); + equivalenceStats.put(codeMapping.getEquivalence(), ++c); + } + + equivalenceStats.forEach((key, value) -> { + g.gridx = 0; + g.gridy++; + add(new JLabel(String.format("%s - %d", key, value)), g); + }); + + // Reviewer g.gridx = 0; g.gridy++; l = new JLabel("By reviewer:"); l.setFont(headerFont); add(l, g); - Map> reviewerResults = new HashMap<>(); + Map> reviewerStats = new HashMap<>(); for (CodeMapping codeMapping : codeMappings) { - reviewerResults.putIfAbsent(codeMapping.getAssignedReviewer(), new Pair<>(0,0)); - Pair c = reviewerResults.get(codeMapping.getAssignedReviewer()); + reviewerStats.putIfAbsent(codeMapping.getAssignedReviewer(), new Pair<>(0,0)); + Pair c = reviewerStats.get(codeMapping.getAssignedReviewer()); Integer nApproved = c.getItem1(); if (codeMapping.getMappingStatus() == CodeMapping.MappingStatus.APPROVED) { c.setItem1(++nApproved); @@ -88,27 +110,28 @@ public ShowReviewStatsDialog() { c.setItem2(++nTotal); } - reviewerResults.forEach((key, value) -> { + reviewerStats.forEach((key, value) -> { g.gridx = 0; g.gridy++; add(new JLabel(String.format("%s - %d/%d", key, value.getItem1(), value.getItem2())), g); }); + // Number of target mappings g.gridx = 0; g.gridy++; l = new JLabel("By number of targets:"); l.setFont(headerFont); add(l, g); - Map oneToManyResults = new HashMap<>(); + Map nTargetsStats = new HashMap<>(); for (CodeMapping codeMapping : codeMappings) { Integer nTargets = codeMapping.getTargetConcepts().size(); - oneToManyResults.putIfAbsent(nTargets, 0); - Integer c = oneToManyResults.get(nTargets); - oneToManyResults.put(nTargets, ++c); + nTargetsStats.putIfAbsent(nTargets, 0); + Integer c = nTargetsStats.get(nTargets); + nTargetsStats.put(nTargets, ++c); } - oneToManyResults.forEach((key, value) -> { + nTargetsStats.forEach((key, value) -> { g.gridx = 0; g.gridy++; add(new JLabel(String.format("%d - %d", key, value)), g); From 8caa4e5b4a0892235b7b2cc9cfc675e6f5de02b2 Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Mon, 15 Mar 2021 16:00:56 +0100 Subject: [PATCH 14/17] refactor count by logic --- .../ohdsi/usagi/ui/ShowReviewStatsDialog.java | 58 +++++++------------ 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java index ccdd642..c34cc09 100644 --- a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java +++ b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class ShowReviewStatsDialog extends JDialog { @@ -58,14 +59,10 @@ public ShowReviewStatsDialog() { l.setFont(headerFont); add(l, g); - Map mappingStats = new HashMap<>(); - for (CodeMapping codeMapping : codeMappings) { - mappingStats.putIfAbsent(codeMapping.getMappingStatus(), 0); - Integer c = mappingStats.get(codeMapping.getMappingStatus()); - mappingStats.put(codeMapping.getMappingStatus(), ++c); - } + Map countByMappingStatus = codeMappings.stream() + .collect(Collectors.groupingBy(CodeMapping::getMappingStatus, Collectors.counting())); - mappingStats.forEach((key, value) -> { + countByMappingStatus.forEach((key, value) -> { g.gridx = 0; g.gridy++; add(new JLabel(String.format("%s - %d", key, value)), g); @@ -78,14 +75,10 @@ public ShowReviewStatsDialog() { l.setFont(headerFont); add(l, g); - Map equivalenceStats = new HashMap<>(); - for (CodeMapping codeMapping : codeMappings) { - equivalenceStats.putIfAbsent(codeMapping.getEquivalence(), 0); - Integer c = equivalenceStats.get(codeMapping.getEquivalence()); - equivalenceStats.put(codeMapping.getEquivalence(), ++c); - } + Map countByEquivalence = codeMappings.stream() + .collect(Collectors.groupingBy(CodeMapping::getEquivalence, Collectors.counting())); - equivalenceStats.forEach((key, value) -> { + countByEquivalence.forEach((key, value) -> { g.gridx = 0; g.gridy++; add(new JLabel(String.format("%s - %d", key, value)), g); @@ -94,44 +87,35 @@ public ShowReviewStatsDialog() { // Reviewer g.gridx = 0; g.gridy++; - l = new JLabel("By reviewer:"); + l = new JLabel("By assigned reviewer:"); l.setFont(headerFont); add(l, g); - Map> reviewerStats = new HashMap<>(); - for (CodeMapping codeMapping : codeMappings) { - reviewerStats.putIfAbsent(codeMapping.getAssignedReviewer(), new Pair<>(0,0)); - Pair c = reviewerStats.get(codeMapping.getAssignedReviewer()); - Integer nApproved = c.getItem1(); - if (codeMapping.getMappingStatus() == CodeMapping.MappingStatus.APPROVED) { - c.setItem1(++nApproved); - } - Integer nTotal = c.getItem2(); - c.setItem2(++nTotal); - } + Map countByAssignedReviewer = codeMappings.stream() + .collect(Collectors.groupingBy(CodeMapping::getAssignedReviewer, Collectors.counting())); - reviewerStats.forEach((key, value) -> { + Map countApprovedByAssignedReviewer = codeMappings.stream() + .filter(x -> x.getMappingStatus().equals(CodeMapping.MappingStatus.APPROVED)) + .collect(Collectors.groupingBy(CodeMapping::getAssignedReviewer, Collectors.counting())); + + countByAssignedReviewer.forEach((key, total) -> { g.gridx = 0; g.gridy++; - add(new JLabel(String.format("%s - %d/%d", key, value.getItem1(), value.getItem2())), g); + long nApproved = countApprovedByAssignedReviewer.getOrDefault(key, 0L); + add(new JLabel(String.format("%s - %d/%d", key, nApproved, total)), g); }); // Number of target mappings g.gridx = 0; g.gridy++; - l = new JLabel("By number of targets:"); + l = new JLabel("By number of target concepts:"); l.setFont(headerFont); add(l, g); - Map nTargetsStats = new HashMap<>(); - for (CodeMapping codeMapping : codeMappings) { - Integer nTargets = codeMapping.getTargetConcepts().size(); - nTargetsStats.putIfAbsent(nTargets, 0); - Integer c = nTargetsStats.get(nTargets); - nTargetsStats.put(nTargets, ++c); - } + Map countByNumberOfTargetConcepts = codeMappings.stream() + .collect(Collectors.groupingBy(x -> x.getTargetConcepts().size(), Collectors.counting())); - nTargetsStats.forEach((key, value) -> { + countByNumberOfTargetConcepts.forEach((key, value) -> { g.gridx = 0; g.gridy++; add(new JLabel(String.format("%d - %d", key, value)), g); From 798d33e32d8316594bad9431fb1796a6e7cf944b Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Mon, 15 Mar 2021 16:09:34 +0100 Subject: [PATCH 15/17] further refactoring --- .../ohdsi/usagi/ui/ShowReviewStatsDialog.java | 71 +++++++------------ 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java index c34cc09..cff349e 100644 --- a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java +++ b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java @@ -16,11 +16,9 @@ package org.ohdsi.usagi.ui; import org.ohdsi.usagi.CodeMapping; -import org.ohdsi.utilities.collections.Pair; import javax.swing.*; import java.awt.*; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -29,9 +27,10 @@ public class ShowReviewStatsDialog extends JDialog { private static final long serialVersionUID = 2028328868610404663L; - public ShowReviewStatsDialog() { - Font headerFont = new Font("Arial", Font.BOLD,12); + private static final Font HEADER_FONT = new Font("Arial", Font.BOLD,12); + public ShowReviewStatsDialog() { + // If selection of multiple codes made, then use that to calculate statistics java.util.List selectedCodeMappings = Global.mappingTablePanel.getSelectedCodeMappings(); List codeMappings; if (selectedCodeMappings.size() > 1) { @@ -45,51 +44,31 @@ public ShowReviewStatsDialog() { GridBagConstraints g = new GridBagConstraints(); g.fill = GridBagConstraints.BOTH; - g.ipadx = 50; + g.ipadx = 10; g.ipady = 10; g.gridx = 0; g.gridy = 0; - add(new JLabel(String.format("Number of (selected) source codes: %d", codeMappings.size())), g); + addLabel(g, String.format("Number of (selected) source codes: %d", codeMappings.size())); // Mapping status - g.gridx = 0; - g.gridy++; - JLabel l = new JLabel("By mapping status:"); - l.setFont(headerFont); - add(l, g); + addHeaderLabel(g, "By mapping status:"); Map countByMappingStatus = codeMappings.stream() .collect(Collectors.groupingBy(CodeMapping::getMappingStatus, Collectors.counting())); - countByMappingStatus.forEach((key, value) -> { - g.gridx = 0; - g.gridy++; - add(new JLabel(String.format("%s - %d", key, value)), g); - }); + countByMappingStatus.forEach((key, value) -> addLabel(g, String.format("%s - %d", key, value))); // Equivalence status - g.gridx = 0; - g.gridy++; - l = new JLabel("By equivalence status:"); - l.setFont(headerFont); - add(l, g); + addHeaderLabel(g,"By equivalence status:"); Map countByEquivalence = codeMappings.stream() .collect(Collectors.groupingBy(CodeMapping::getEquivalence, Collectors.counting())); - countByEquivalence.forEach((key, value) -> { - g.gridx = 0; - g.gridy++; - add(new JLabel(String.format("%s - %d", key, value)), g); - }); + countByEquivalence.forEach((key, value) -> addLabel(g, String.format("%s - %d", key, value))); // Reviewer - g.gridx = 0; - g.gridy++; - l = new JLabel("By assigned reviewer:"); - l.setFont(headerFont); - add(l, g); + addHeaderLabel(g,"By assigned reviewer:"); Map countByAssignedReviewer = codeMappings.stream() .collect(Collectors.groupingBy(CodeMapping::getAssignedReviewer, Collectors.counting())); @@ -99,27 +78,17 @@ public ShowReviewStatsDialog() { .collect(Collectors.groupingBy(CodeMapping::getAssignedReviewer, Collectors.counting())); countByAssignedReviewer.forEach((key, total) -> { - g.gridx = 0; - g.gridy++; long nApproved = countApprovedByAssignedReviewer.getOrDefault(key, 0L); - add(new JLabel(String.format("%s - %d/%d", key, nApproved, total)), g); + addLabel(g, String.format("%s - %d/%d", key, nApproved, total)); }); // Number of target mappings - g.gridx = 0; - g.gridy++; - l = new JLabel("By number of target concepts:"); - l.setFont(headerFont); - add(l, g); + addHeaderLabel(g,"By number of target concepts:"); Map countByNumberOfTargetConcepts = codeMappings.stream() .collect(Collectors.groupingBy(x -> x.getTargetConcepts().size(), Collectors.counting())); - countByNumberOfTargetConcepts.forEach((key, value) -> { - g.gridx = 0; - g.gridy++; - add(new JLabel(String.format("%d - %d", key, value)), g); - }); + countByNumberOfTargetConcepts.forEach((key, value) -> addLabel(g, String.format("%d - %d", key, value))); g.gridx = 0; g.gridy++; @@ -143,6 +112,20 @@ public ShowReviewStatsDialog() { } + private JLabel addLabel(GridBagConstraints g, String message) { + g.gridx = 0; + g.gridy++; + JLabel label = new JLabel(message); + add(label, g); + return label; + } + + private JLabel addHeaderLabel(GridBagConstraints g, String message) { + JLabel label = addLabel(g, message); + label.setFont(HEADER_FONT); + return label; + } + private void close() { setVisible(false); } From 9a0b05388c3e0b919a096ed6d4f7d32beb70cc6f Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Mon, 15 Mar 2021 16:24:13 +0100 Subject: [PATCH 16/17] change serialVersionUID --- src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java index cff349e..9d6a599 100644 --- a/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java +++ b/src/org/ohdsi/usagi/ui/ShowReviewStatsDialog.java @@ -25,7 +25,7 @@ public class ShowReviewStatsDialog extends JDialog { - private static final long serialVersionUID = 2028328868610404663L; + private static final long serialVersionUID = -4646761336953654777L; private static final Font HEADER_FONT = new Font("Arial", Font.BOLD,12); From 08fd549ac3ce60b5335c53126aab3f5724da8ddd Mon Sep 17 00:00:00 2001 From: Maxim Moinat Date: Mon, 15 Mar 2021 17:17:00 +0100 Subject: [PATCH 17/17] bump version --- src/org/ohdsi/usagi/ui/UsagiMain.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/ohdsi/usagi/ui/UsagiMain.java b/src/org/ohdsi/usagi/ui/UsagiMain.java index bd82fc6..4519742 100644 --- a/src/org/ohdsi/usagi/ui/UsagiMain.java +++ b/src/org/ohdsi/usagi/ui/UsagiMain.java @@ -41,7 +41,7 @@ */ public class UsagiMain implements ActionListener { - public static String version = "1.4.2-SNAPSHOT"; + public static String version = "1.4.2"; public static void main(String[] args) { new UsagiMain(args);