getBaselineChange() {
121 | return Optional.ofNullable(baselineChange);
122 | }
123 |
124 | @Override
125 | public void setBaselineChange(OWLOntologyChange change) {
126 | this.baselineChange = checkNotNull(change);
127 | }
128 |
129 | @Override
130 | public boolean equals(Object o) {
131 | if (this == o) return true;
132 | if (o == null || getClass() != o.getClass()) return false;
133 | ChangeImpl change = (ChangeImpl) o;
134 | return Objects.equal(id, change.id) &&
135 | Objects.equal(changes, change.changes) &&
136 | Objects.equal(commitMetadata, change.commitMetadata) &&
137 | mode == change.mode &&
138 | Objects.equal(details, change.details) &&
139 | Objects.equal(conflictingChanges, change.conflictingChanges) &&
140 | Objects.equal(baselineChange, change.baselineChange) &&
141 | Objects.equal(review, change.review);
142 | }
143 |
144 | @Override
145 | public int hashCode() {
146 | return Objects.hashCode(id, changes, commitMetadata, mode, details, conflictingChanges, baselineChange, review);
147 | }
148 |
149 | @Override
150 | public String toString() {
151 | return MoreObjects.toStringHelper(this)
152 | .add("id", id)
153 | .add("changes", changes)
154 | .add("commitMetadata", commitMetadata)
155 | .add("mode", mode)
156 | .add("details", details)
157 | .add("conflictingChanges", conflictingChanges)
158 | .add("baselineChange", baselineChange)
159 | .add("review", review)
160 | .toString();
161 | }
162 |
163 | @Override
164 | public int compareTo(Change that) {
165 | return ComparisonChain.start()
166 | .compare(this.details.getSubject(), that.getDetails().getSubject())
167 | .result();
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/editor/owl/client/diff/ui/ChangeDetailsPanel.java:
--------------------------------------------------------------------------------
1 | package org.protege.editor.owl.client.diff.ui;
2 |
3 | import org.protege.editor.core.Disposable;
4 | import org.protege.editor.owl.OWLEditorKit;
5 | import org.protege.editor.owl.client.diff.model.*;
6 | import org.protege.editor.owl.model.OWLModelManager;
7 |
8 | import javax.swing.*;
9 | import javax.swing.border.EmptyBorder;
10 | import java.awt.*;
11 |
12 | import static com.google.common.base.Preconditions.checkNotNull;
13 |
14 | /**
15 | * @author Rafael Gonçalves
16 | * Stanford Center for Biomedical Informatics Research
17 | */
18 | public class ChangeDetailsPanel extends JPanel implements Disposable {
19 | private OWLEditorKit editorKit;
20 | private LogDiffManager diffManager;
21 |
22 | /**
23 | * Constructor
24 | *
25 | * @param modelManager OWL model manager
26 | * @param editorKit OWL editor kit
27 | */
28 | public ChangeDetailsPanel(OWLModelManager modelManager, OWLEditorKit editorKit) {
29 | this.editorKit = checkNotNull(editorKit);
30 |
31 | diffManager = LogDiffManager.get(modelManager, editorKit);
32 | diffManager.addListener(diffListener);
33 |
34 | setLayout(new BorderLayout());
35 | setBorder(GuiUtils.MATTE_BORDER);
36 | setBackground(GuiUtils.WHITE_BACKGROUND);
37 |
38 | createContents();
39 | }
40 |
41 | private LogDiffListener diffListener = new LogDiffListener() {
42 | @Override
43 | public void statusChanged(LogDiffEvent event) {
44 | if (event.equals(LogDiffEvent.CHANGE_SELECTION_CHANGED)) {
45 | if(!diffManager.getSelectedChanges().isEmpty()) {
46 | removeAll();
47 | createContents();
48 | }
49 | }
50 | else if(event.equals(LogDiffEvent.AUTHOR_SELECTION_CHANGED) || event.equals(LogDiffEvent.COMMIT_SELECTION_CHANGED) || event.equals(LogDiffEvent.ONTOLOGY_UPDATED)) {
51 | removeAll();
52 | repaint();
53 | }
54 | // rpc: when review view is active and a change is reviewed, recreate the review panel
55 | }
56 | };
57 |
58 | private void createContents() {
59 | if(!diffManager.getSelectedChanges().isEmpty()) {
60 | Change change = diffManager.getFirstSelectedChange();
61 | if (change != null) {
62 | addDetailsTable(change);
63 | revalidate();
64 | }
65 | }
66 | }
67 |
68 | private void addDetailsTable(Change change) {
69 | ChangeDetailsTableModel tableModel;
70 | if(change.getBaselineChange().isPresent()) {
71 | tableModel = new MatchingChangeDetailsTableModel();
72 | }
73 | else {
74 | tableModel = new MultipleChangeDetailsTableModel();
75 | }
76 | tableModel.setChange(change);
77 | ChangeDetailsTable table = new ChangeDetailsTable(tableModel, editorKit);
78 |
79 | JScrollPane scrollPane = new JScrollPane(table);
80 | scrollPane.setBorder(GuiUtils.EMPTY_BORDER);
81 | add(scrollPane, BorderLayout.CENTER);
82 | }
83 |
84 | @SuppressWarnings("unused") // rpc
85 | private void addReview(Change change) {
86 | JPanel reviewPanel = new JPanel(new BorderLayout());
87 | JLabel reviewLbl = new JLabel();
88 | Icon icon = null;
89 | String statusStr = "";
90 | ReviewStatus status = change.getReviewStatus();
91 | switch(status) {
92 | case ACCEPTED:
93 | icon = GuiUtils.getIcon(GuiUtils.REVIEW_ACCEPTED_ICON_FILENAME, 40, 40);
94 | statusStr = "Accepted"; break;
95 | case REJECTED:
96 | icon = GuiUtils.getIcon(GuiUtils.REVIEW_REJECTED_ICON_FILENAME, 40, 40);
97 | statusStr = "Rejected"; break;
98 | case PENDING:
99 | icon = GuiUtils.getIcon(GuiUtils.REVIEW_PENDING_ICON_FILENAME, 40, 40);
100 | statusStr = "Pending Review"; break;
101 | }
102 | if(icon != null) {
103 | reviewLbl.setIcon(icon);
104 | reviewLbl.setIconTextGap(10);
105 | }
106 | reviewLbl.setBorder(new EmptyBorder(10, 13, 10, 1));
107 | reviewLbl.setText(getReviewText(change.getReview(), statusStr));
108 | reviewPanel.add(reviewLbl);
109 | add(reviewPanel, BorderLayout.SOUTH);
110 | }
111 |
112 | private String getReviewText(Review review, String statusStr) {
113 | String dateStr = "", author = "", comment = "";
114 | if(review != null) {
115 | if (review.getDate().isPresent()) {
116 | dateStr = GuiUtils.getShortenedFormattedDate(review.getDate().get());
117 | }
118 | author = (review.getAuthor().isPresent() ? review.getAuthor().get().getUserName() : "");
119 | comment = (review.getComment().isPresent() ? review.getComment().get() : "");
120 | }
121 | String reviewText = "" + statusStr + "
";
122 | if(!author.isEmpty() && !dateStr.isEmpty()) {
123 | reviewText += "Reviewed by " + author + " on " + dateStr + "
";
124 | }
125 | if(!comment.isEmpty()) {
126 | reviewText += "Comment: \"" + comment + "\"
";
127 | }
128 | reviewText += "";
129 | return reviewText;
130 | }
131 |
132 | @Override
133 | public void dispose() {
134 | diffManager.removeListener(diffListener);
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/main/resources/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
84 |
85 |
86 |
87 |
88 |
89 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
135 |
136 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
149 |
150 |
151 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/editor/owl/client/diff/ui/ConflictsListPanel.java:
--------------------------------------------------------------------------------
1 | package org.protege.editor.owl.client.diff.ui;
2 |
3 | import org.protege.editor.core.Disposable;
4 | import org.protege.editor.owl.OWLEditorKit;
5 | import org.protege.editor.owl.client.diff.model.*;
6 | import org.protege.editor.owl.model.OWLModelManager;
7 | import org.semanticweb.owlapi.model.OWLOntologyChange;
8 |
9 | import javax.swing.*;
10 | import javax.swing.border.Border;
11 | import javax.swing.border.EmptyBorder;
12 | import java.awt.*;
13 | import java.util.*;
14 | import java.util.stream.Collectors;
15 |
16 | import static com.google.common.base.Preconditions.checkNotNull;
17 |
18 | /**
19 | * @author Rafael Gonçalves
20 | * Stanford Center for Biomedical Informatics Research
21 | */
22 | public class ConflictsListPanel extends JPanel implements Disposable {
23 | private OWLEditorKit editorKit;
24 | private LogDiffManager diffManager;
25 | private LogDiff diff;
26 | private Change change;
27 |
28 | /**
29 | * Constructor
30 | *
31 | * @param modelManager OWL model manager
32 | * @param editorKit OWL editor kit
33 | */
34 | public ConflictsListPanel(OWLModelManager modelManager, OWLEditorKit editorKit) {
35 | this.editorKit = checkNotNull(editorKit);
36 | diffManager = LogDiffManager.get(modelManager, editorKit);
37 | diffManager.addListener(diffListener);
38 | diff = diffManager.getDiffEngine();
39 |
40 | setLayout(new BorderLayout());
41 | setBorder(GuiUtils.MATTE_BORDER);
42 | setBackground(GuiUtils.WHITE_BACKGROUND);
43 | setAlignmentX(LEFT_ALIGNMENT);
44 |
45 | if (!diffManager.getSelectedChanges().isEmpty()) {
46 | change = diffManager.getFirstSelectedChange();
47 | addConflictDetails();
48 | }
49 | }
50 |
51 | private LogDiffListener diffListener = new LogDiffListener() {
52 | @Override
53 | public void statusChanged(LogDiffEvent event) {
54 | if (event.equals(LogDiffEvent.CHANGE_SELECTION_CHANGED)) {
55 | if (!diffManager.getSelectedChanges().isEmpty()) {
56 | change = diffManager.getFirstSelectedChange();
57 | removeAll();
58 | addConflictDetails();
59 | }
60 | } else if (event.equals(LogDiffEvent.AUTHOR_SELECTION_CHANGED) || event.equals(LogDiffEvent.COMMIT_SELECTION_CHANGED) || event.equals(LogDiffEvent.ONTOLOGY_UPDATED)) {
61 | removeAll(); repaint();
62 | }
63 | }
64 | };
65 |
66 | private GridBagConstraints createGridBagConstraints() {
67 | GridBagConstraints c = new GridBagConstraints();
68 | c.gridwidth = 1;
69 | c.fill = GridBagConstraints.HORIZONTAL;
70 | c.gridx = 0;
71 | c.gridy = 0;
72 | c.anchor = GridBagConstraints.WEST;
73 | c.weighty = 0;
74 | c.weightx = 1;
75 | c.insets = new Insets(0, 5, 2, 5);
76 | return c;
77 | }
78 |
79 | private void addConflictDetails() {
80 | if (change != null) {
81 | Set changes = change.getConflictingChanges().stream().map(id -> diff.getChange(id)).collect(Collectors.toSet());
82 | if (!changes.isEmpty()) {
83 | GridBagConstraints bpc = createGridBagConstraints();
84 | add(getConflictsScrollPane(changes, bpc, ""), BorderLayout.CENTER);
85 | } else {
86 | add(createHeaderLabel("No conflicts", Optional.of(new EmptyBorder(5, 6, 0, 0))), BorderLayout.NORTH);
87 | }
88 | repaint();
89 | }
90 | }
91 |
92 | private JScrollPane getConflictsScrollPane(Set changes, GridBagConstraints constraints, String panelHeader) {
93 | JPanel panel = new JPanel(new GridBagLayout());
94 | createSubPanel(panel, changes, constraints, panelHeader);
95 | JScrollPane scrollPane = new JScrollPane(panel);
96 | scrollPane.setBorder(GuiUtils.EMPTY_BORDER);
97 | return scrollPane;
98 | }
99 |
100 | private JLabel createHeaderLabel(String panelHeader, Optional border) {
101 | JLabel label = new JLabel(panelHeader);
102 | label.setFont(getFont().deriveFont(Font.BOLD));
103 | if(border.isPresent()) {
104 | label.setBorder(border.get());
105 | }
106 | return label;
107 | }
108 |
109 | private void createSubPanel(JPanel parent, Set changes, GridBagConstraints con, String panelHeader) {
110 | parent.add(createHeaderLabel(panelHeader, Optional.empty()), con);
111 | con.gridy = con.gridy + 1;
112 | parent.add(new JSeparator(SwingConstants.HORIZONTAL), con);
113 | con.gridy = con.gridy + 1;
114 |
115 | parent.setAlignmentX(LEFT_ALIGNMENT);
116 | parent.setBackground(GuiUtils.WHITE_BACKGROUND);
117 | parent.setBorder(new EmptyBorder(5, 1, 1, 1));
118 | if (!changes.isEmpty()) {
119 | createConflictsPanel(parent, changes, con);
120 | }
121 | // fill the remaining panel if necessary
122 | con.weightx = 1;
123 | con.weighty = 1;
124 | con.fill = GridBagConstraints.BOTH;
125 | parent.add(new JLabel(), con);
126 | }
127 |
128 | private void createConflictsPanel(JPanel panel, Set changes, GridBagConstraints con) {
129 | Map> map = new HashMap<>();
130 | for (Change change : changes) {
131 | CommitMetadata metadata = change.getCommitMetadata();
132 | if (map.containsKey(metadata)) {
133 | Set ontChanges = map.get(metadata);
134 | ontChanges.addAll(change.getChanges());
135 | map.put(metadata, ontChanges);
136 | } else {
137 | map.put(metadata, change.getChanges());
138 | }
139 | }
140 | int counter = 1;
141 | for (CommitMetadata cd : map.keySet()) {
142 | Set ontChanges = map.get(cd);
143 | ConflictingCommitPanel commitPanel = new ConflictingCommitPanel(editorKit, ontChanges, cd.getDate(), cd.getAuthor(), cd.getComment(), counter);
144 | panel.add(commitPanel, con);
145 | con.gridy = con.gridy + 1;
146 |
147 | panel.add(new JSeparator(SwingConstants.HORIZONTAL), con);
148 | con.gridy = con.gridy + 1;
149 | counter++;
150 | }
151 | }
152 |
153 | @Override
154 | public void dispose() {
155 | diffManager.removeListener(diffListener);
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.sonatype.oss
9 | oss-parent
10 | 7
11 |
12 |
13 | edu.stanford.protege
14 | protege-client
15 | 3.0.0-SNAPSHOT
16 | bundle
17 |
18 | Protege Client
19 | Provides client functionality for Protege 5 to connect to a Protege Server, allowing end users to collaboratively edit collections of OWL ontologies.
20 |
21 |
22 | Stanford Center for Biomedical Informatics Research
23 | http://bmir.stanford.edu/
24 |
25 |
26 |
27 |
28 | GNU Lesser General Public License
29 | http://www.gnu.org/copyleft/lesser.html
30 |
31 |
32 |
33 |
34 |
35 | Timothy Redmond
36 | tredmond@stanford.edu
37 |
38 |
39 |
40 |
41 | scm:git:git@github.com:protegeproject/protege-client.git
42 | scm:git:git@github.com:protegeproject/protege-client.git
43 | https://github.com/protegeproject/protege-client
44 |
45 |
46 |
47 | UTF-8
48 | 5.0.0-beta-21
49 | 3.0.0-SNAPSHOT
50 |
51 |
52 |
53 |
54 | edu.stanford.protege
55 | protege-editor-core
56 | ${protege.version}
57 |
58 |
59 |
60 | edu.stanford.protege
61 | protege-editor-owl
62 | ${protege.version}
63 |
64 |
65 |
66 | edu.stanford.protege
67 | protege-server
68 | ${protege-server.version}
69 |
70 |
71 |
72 | com.fasterxml.uuid
73 | java-uuid-generator
74 | 3.1.3
75 |
76 |
77 |
78 |
79 |
80 |
81 | org.apache.maven.plugins
82 | maven-compiler-plugin
83 | 3.3
84 |
85 | 1.8
86 | 1.8
87 |
88 |
89 |
90 |
91 | org.apache.felix
92 | maven-bundle-plugin
93 | 3.0.1
94 | true
95 |
96 |
97 | .
98 | org.protege.editor.owl.client;singleton:=true
99 | ${project.version}
100 | The Protege Development Team
101 |
102 | org.protege.editor.owl.client*;version=${project.version},
103 | com.fasterxml.uuid.*
104 |
105 |
106 | org.protege.editor.core.*;version="5.0",
107 | org.protege.editor.owl.client.*;version=${project.version},
108 | org.protege.editor.owl.*;version="5.0",
109 | com.fasterxml.uuid.*,
110 | *
111 |
112 | {maven-resources}
113 |
114 |
115 |
116 |
117 | bundle-manifest
118 | install
119 |
120 | manifest
121 |
122 |
123 |
124 |
125 |
126 |
127 | org.apache.maven.plugins
128 | maven-source-plugin
129 | 2.4
130 |
131 |
132 | attach-sources
133 |
134 | jar
135 |
136 |
137 |
138 |
139 |
140 |
141 | org.apache.maven.plugins
142 | maven-javadoc-plugin
143 | 2.10.3
144 |
145 |
146 | attach-javadocs
147 |
148 | jar
149 |
150 |
151 | -Xdoclint:none
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/editor/owl/client/panel/ChangeHistoryPanel.java:
--------------------------------------------------------------------------------
1 | package org.protege.editor.owl.client.panel;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.Component;
5 | import java.awt.Dimension;
6 | import java.awt.Font;
7 | import java.awt.Insets;
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 | import java.text.SimpleDateFormat;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | import javax.swing.BorderFactory;
15 | import javax.swing.Box;
16 | import javax.swing.BoxLayout;
17 | import javax.swing.JButton;
18 | import javax.swing.JComponent;
19 | import javax.swing.JDialog;
20 | import javax.swing.JLabel;
21 | import javax.swing.JPanel;
22 | import javax.swing.JScrollPane;
23 | import javax.swing.JTable;
24 | import javax.swing.RowSorter;
25 | import javax.swing.SortOrder;
26 | import javax.swing.event.ListSelectionEvent;
27 | import javax.swing.event.ListSelectionListener;
28 | import javax.swing.table.TableCellRenderer;
29 | import javax.swing.table.TableColumnModel;
30 | import javax.swing.table.TableModel;
31 | import javax.swing.table.TableRowSorter;
32 |
33 | import org.protege.editor.owl.OWLEditorKit;
34 | import org.protege.editor.owl.ui.renderer.OWLCellRenderer;
35 | import org.protege.owl.server.api.ChangeHistory;
36 | import org.protege.owl.server.api.OntologyDocumentRevision;
37 | import org.semanticweb.owlapi.model.OWLObject;
38 | import org.semanticweb.owlapi.model.OWLOntology;
39 | import org.semanticweb.owlapi.model.OWLOntologyChange;
40 | import org.semanticweb.owlapi.model.OWLOntologyID;
41 |
42 | public class ChangeHistoryPanel extends JDialog {
43 |
44 | private static final long serialVersionUID = -372532962143290188L;
45 | private OWLEditorKit editorKit;
46 | private OWLOntology ontology;
47 | private ChangeHistory changes;
48 | private JTable changeListTable;
49 | private ChangeListTableModel changeListTableModel;
50 |
51 | public ChangeHistoryPanel(OWLEditorKit editorKit, ChangeHistory changes) {
52 | this.editorKit = editorKit;
53 | this.ontology = editorKit.getOWLModelManager().getActiveOntology();
54 | this.changes = changes;
55 | initUI();
56 | }
57 |
58 | private void initUI() {
59 | String shortOntologyName = "";
60 | OWLOntologyID ontologyId = ontology.getOntologyID();
61 | if (!ontologyId.isAnonymous()) {
62 | shortOntologyName = ontology.getOntologyID().getOntologyIRI().get().getRemainder().get();
63 | }
64 | if (shortOntologyName.isEmpty()) {
65 | shortOntologyName = ontologyId.toString();
66 | }
67 | setTitle("Change History for " + shortOntologyName);
68 | setPreferredSize(new Dimension(800, 600));
69 | setModal(true);
70 |
71 | JPanel wrapper = new JPanel();
72 | wrapper.setLayout(new BorderLayout());
73 | wrapper.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
74 |
75 | // Changes list
76 | JPanel panel = new JPanel();
77 | panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
78 |
79 | JLabel label = new JLabel("Changes List");
80 | label.setAlignmentX(Component.LEFT_ALIGNMENT);
81 | Font font = label.getFont().deriveFont(Font.BOLD);
82 | label.setFont(font);
83 | panel.add(label);
84 | panel.add(Box.createRigidArea(new Dimension(0,5)));
85 | panel.add(getHistoryComponent());
86 | panel.add(Box.createRigidArea(new Dimension(0,11)));
87 |
88 | // Change details
89 | label = new JLabel("Change Details");
90 | label.setAlignmentX(Component.LEFT_ALIGNMENT);
91 | label.setFont(font);
92 | panel.add(label);
93 | panel.add(Box.createRigidArea(new Dimension(0,5)));
94 | panel.add(getChangeListComponent());
95 | panel.add(Box.createRigidArea(new Dimension(0,17)));
96 |
97 | wrapper.add(panel, BorderLayout.CENTER);
98 |
99 | // OK button
100 | JButton button = new JButton("OK");
101 | ActionListener listener = new ActionListener() {
102 |
103 | @Override
104 | public void actionPerformed(ActionEvent e) {
105 | setVisible(false);
106 | }
107 | };
108 | button.addActionListener(listener);
109 | button.setMargin(new Insets(button.getInsets().top, 12, button.getInsets().bottom, 12));
110 | panel = new JPanel();
111 | panel.add(button);
112 |
113 | wrapper.add(panel, BorderLayout.SOUTH);
114 |
115 | getContentPane().add(wrapper);
116 |
117 | // TODO Why doesn't this work?
118 | //getRootPane().setDefaultButton(button);
119 |
120 | pack();
121 | setResizable(true);
122 | }
123 |
124 | private JComponent getHistoryComponent() {
125 | HistoryTableModel model = new HistoryTableModel(changes);
126 | final JTable table = new JTable(model);
127 | table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
128 |
129 | @Override
130 | public void valueChanged(ListSelectionEvent listSelectionEvent) {
131 | List changesToDisplay = new ArrayList();
132 | for (int row : table.getSelectedRows()) {
133 | OntologyDocumentRevision start = changes.getStartRevision().add(table.convertRowIndexToModel(row));
134 | changesToDisplay.addAll(changes.cropChanges(start, start.next()).getChanges(ontology));
135 | }
136 | changeListTableModel.setChangeList(changesToDisplay);
137 | }
138 | });
139 |
140 | SimpleDateFormat format = new SimpleDateFormat("MMM dd, yyyy hh:mm a, z");
141 | TableCellRenderer renderer = new FormatRenderer(format);
142 | TableColumnModel columnModel = table.getColumnModel();
143 | columnModel.getColumn(0).setCellRenderer(renderer);
144 |
145 | // Allow user to sort
146 | TableRowSorter sorter = new TableRowSorter(model);
147 | table.setRowSorter(sorter);
148 |
149 | // Sort initially by the date column in descending order
150 | List sortKeys = new ArrayList();
151 | sortKeys.add(new RowSorter.SortKey(0, SortOrder.DESCENDING));
152 | sorter.setSortKeys(sortKeys);
153 |
154 | JScrollPane scrollPane = new JScrollPane(table);
155 | scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
156 | return scrollPane;
157 | }
158 |
159 | private JComponent getChangeListComponent() {
160 | changeListTableModel = new ChangeListTableModel(new ArrayList());
161 | changeListTable = new JTable(changeListTableModel);
162 | changeListTable.setDefaultRenderer(OWLObject.class, new OWLCellRenderer(editorKit));
163 | JScrollPane scrollPane = new JScrollPane(changeListTable);
164 | scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
165 | return scrollPane;
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/editor/owl/client/connect/ServerConnectionManager.java:
--------------------------------------------------------------------------------
1 | package org.protege.editor.owl.client.connect;
2 |
3 | import org.protege.editor.core.editorkit.plugin.EditorKitHook;
4 | import org.protege.editor.core.ui.error.ErrorLogPanel;
5 | import org.protege.editor.owl.OWLEditorKit;
6 | import org.protege.editor.owl.model.OWLModelManager;
7 | import org.protege.editor.owl.model.io.IOListener;
8 | import org.protege.editor.owl.model.io.IOListenerEvent;
9 | import org.protege.owl.server.api.client.Client;
10 | import org.protege.owl.server.api.client.VersionedOntologyDocument;
11 | import org.protege.owl.server.api.exception.OWLServerException;
12 | import org.protege.owl.server.util.ClientRegistry;
13 | import org.semanticweb.owlapi.model.*;
14 |
15 | import java.io.IOException;
16 | import java.util.List;
17 | import java.util.Map;
18 | import java.util.TreeMap;
19 | import java.util.concurrent.Executors;
20 | import java.util.concurrent.ScheduledExecutorService;
21 | import java.util.concurrent.ThreadFactory;
22 | import java.util.concurrent.TimeUnit;
23 | import java.util.logging.Logger;
24 |
25 | public class ServerConnectionManager extends EditorKitHook {
26 | public static String ID = "org.protege.editor.owl.client.ServerConnectionManager";
27 | private Logger logger = Logger.getLogger(ServerConnectionManager.class.getCanonicalName());
28 |
29 | public static ServerConnectionManager get(OWLEditorKit editorKit) {
30 | return (ServerConnectionManager) editorKit.get(ID);
31 | }
32 |
33 | private ClientRegistry registry = new ClientRegistry();
34 | private Map ontologyMap = new TreeMap();
35 |
36 | private ScheduledExecutorService singleThreadExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
37 | @Override
38 | public Thread newThread(Runnable r) {
39 | Thread th = new Thread(r, "Client-Server Communications");
40 | th.setDaemon(true);
41 | return th;
42 | }
43 | });
44 |
45 | private IOListener ioListener = new IOListener() {
46 |
47 | @Override
48 | public void beforeSave(IOListenerEvent event) {
49 |
50 | }
51 |
52 | @Override
53 | public void beforeLoad(IOListenerEvent event) {
54 |
55 | }
56 |
57 | @Override
58 | public void afterSave(IOListenerEvent event) {
59 | OWLOntologyID id = event.getOntologyID();
60 | VersionedOntologyDocument vont = ontologyMap.get(id);
61 | if (vont != null) {
62 | try {
63 | vont.saveMetaData();
64 | }
65 | catch (IOException ioe) {
66 | ErrorLogPanel.showErrorDialog(ioe);
67 | }
68 | }
69 | }
70 |
71 | @Override
72 | public void afterLoad(IOListenerEvent event) {
73 | try {
74 | OWLOntologyManager manager = getOWLOntologyManager();
75 | OWLOntologyID id = event.getOntologyID();
76 | OWLOntology ontology = manager.getOntology(id);
77 | if (ontology != null && registry.hasSuitableMetaData(ontology)) {
78 | addVersionedOntology(registry.getVersionedOntologyDocument(ontology));
79 | }
80 | }
81 | catch (IOException ioe) {
82 | ErrorLogPanel.showErrorDialog(ioe);
83 | }
84 | }
85 | };
86 |
87 | private OWLOntologyChangeListener ontologyIdChangeListener = new OWLOntologyChangeListener() {
88 | public void ontologiesChanged(List extends OWLOntologyChange> changes) throws OWLException {
89 | for (OWLOntologyChange change : changes) {
90 | if (change instanceof SetOntologyID) {
91 | SetOntologyID idChange = (SetOntologyID) change;
92 | OWLOntologyID originalId = idChange.getOriginalOntologyID();
93 | VersionedOntologyDocument vont = ontologyMap.remove(originalId);
94 | if (vont != null) {
95 | OWLOntologyID newId = idChange.getNewOntologyID();
96 | ontologyMap.put(newId, vont);
97 | }
98 | }
99 | }
100 | }
101 | };
102 |
103 | @Override
104 | protected OWLEditorKit getEditorKit() {
105 | return (OWLEditorKit) super.getEditorKit();
106 | }
107 |
108 | protected OWLModelManager getOWLModelManager() {
109 | return getEditorKit().getOWLModelManager();
110 | }
111 |
112 | protected OWLOntologyManager getOWLOntologyManager() {
113 | return getEditorKit().getOWLModelManager().getOWLOntologyManager();
114 | }
115 |
116 | @Override
117 | public void initialise() throws Exception {
118 | registry.addFactory(new RMIClientFactory(getEditorKit().getOWLWorkspace()));
119 | getOWLModelManager().addIOListener(ioListener);
120 | getOWLOntologyManager().addOntologyChangeListener(ontologyIdChangeListener);
121 | }
122 |
123 | @Override
124 | public void dispose() throws InterruptedException {
125 | getOWLModelManager().removeIOListener(ioListener);
126 | getOWLOntologyManager().removeOntologyChangeListener(ontologyIdChangeListener);
127 | singleThreadExecutorService.shutdown();
128 | singleThreadExecutorService.awaitTermination(5, TimeUnit.MINUTES);
129 | }
130 |
131 | public ScheduledExecutorService getSingleThreadExecutorService() {
132 | return singleThreadExecutorService;
133 | }
134 |
135 | public VersionedOntologyDocument getVersionedOntology(OWLOntology ontology) {
136 | return ontologyMap.get(ontology.getOntologyID());
137 | }
138 |
139 | public void addVersionedOntology(VersionedOntologyDocument vont) {
140 | OWLOntologyID id = vont.getOntology().getOntologyID();
141 | ontologyMap.put(id, vont);
142 | }
143 |
144 | public Client createClient(OWLOntology ontology) throws OWLServerException {
145 | VersionedOntologyDocument vont = ontologyMap.get(ontology.getOntologyID());
146 | if (vont != null) {
147 | return registry.connectToServer(vont.getServerDocument().getServerLocation());
148 | }
149 | return null;
150 | }
151 |
152 | public Client createClient(IRI serverLocation) throws OWLServerException {
153 | return registry.connectToServer(serverLocation);
154 | }
155 |
156 | public Client createClient(IRI serverLocation, String username, String password) throws OWLServerException {
157 | return registry.connectToServer(serverLocation, username, password);
158 | }
159 |
160 | public void saveHistoryInBackground(VersionedOntologyDocument vont) {
161 | singleThreadExecutorService.submit(new SaveHistory(vont));
162 | }
163 |
164 | private class SaveHistory implements Runnable {
165 | private VersionedOntologyDocument vont;
166 |
167 | public SaveHistory(VersionedOntologyDocument vont) {
168 | this.vont = vont;
169 | }
170 |
171 | @Override
172 | public void run() {
173 | try {
174 | long startTime = System.currentTimeMillis();
175 | vont.saveLocalHistory();
176 | long interval = System.currentTimeMillis() - startTime;
177 | if (interval > 1000) {
178 | logger.info("Save of history file for " + vont.getOntology().getOntologyID() + " took " + (interval / 1000) + " seconds.");
179 | }
180 | }
181 | catch (Error | RuntimeException | IOException e) {
182 | ErrorLogPanel.showErrorDialog(e);
183 | }
184 | }
185 | }
186 |
187 | }
188 |
--------------------------------------------------------------------------------
/src/main/java/org/protege/editor/owl/client/diff/ui/ConflictsGridPanel.java:
--------------------------------------------------------------------------------
1 | package org.protege.editor.owl.client.diff.ui;
2 |
3 | import org.protege.editor.core.Disposable;
4 | import org.protege.editor.owl.OWLEditorKit;
5 | import org.protege.editor.owl.client.diff.model.*;
6 | import org.protege.editor.owl.model.OWLModelManager;
7 | import org.semanticweb.owlapi.model.OWLOntologyChange;
8 |
9 | import javax.swing.*;
10 | import javax.swing.border.Border;
11 | import javax.swing.border.EmptyBorder;
12 | import java.awt.*;
13 | import java.util.*;
14 | import java.util.stream.Collectors;
15 |
16 | import static com.google.common.base.Preconditions.checkNotNull;
17 |
18 | /**
19 | * @author Rafael Gonçalves
20 | * Stanford Center for Biomedical Informatics Research
21 | */
22 | public class ConflictsGridPanel extends JPanel implements Disposable {
23 | private OWLEditorKit editorKit;
24 | private LogDiffManager diffManager;
25 | private LogDiff diff;
26 | private Change change;
27 |
28 | /**
29 | * Constructor
30 | *
31 | * @param modelManager OWL model manager
32 | * @param editorKit OWL editor kit
33 | */
34 | public ConflictsGridPanel(OWLModelManager modelManager, OWLEditorKit editorKit) {
35 | this.editorKit = checkNotNull(editorKit);
36 | diffManager = LogDiffManager.get(modelManager, editorKit);
37 | diffManager.addListener(diffListener);
38 | diff = diffManager.getDiffEngine();
39 |
40 | setLayout(new BorderLayout());
41 | setBorder(GuiUtils.MATTE_BORDER);
42 | setBackground(GuiUtils.WHITE_BACKGROUND);
43 | setAlignmentX(LEFT_ALIGNMENT);
44 |
45 | if (!diffManager.getSelectedChanges().isEmpty()) {
46 | change = diffManager.getFirstSelectedChange();
47 | addConflictDetails();
48 | }
49 | }
50 |
51 | private LogDiffListener diffListener = new LogDiffListener() {
52 | @Override
53 | public void statusChanged(LogDiffEvent event) {
54 | if (event.equals(LogDiffEvent.CHANGE_SELECTION_CHANGED)) {
55 | if (!diffManager.getSelectedChanges().isEmpty()) {
56 | change = diffManager.getFirstSelectedChange();
57 | removeAll();
58 | addConflictDetails();
59 | }
60 | } else if (event.equals(LogDiffEvent.AUTHOR_SELECTION_CHANGED) || event.equals(LogDiffEvent.COMMIT_SELECTION_CHANGED) || event.equals(LogDiffEvent.ONTOLOGY_UPDATED)) {
61 | removeAll(); repaint();
62 | }
63 | }
64 | };
65 |
66 | private GridBagConstraints createGridBagConstraints() {
67 | GridBagConstraints c = new GridBagConstraints();
68 | c.gridwidth = 1;
69 | c.fill = GridBagConstraints.HORIZONTAL;
70 | c.gridx = 0;
71 | c.gridy = 0;
72 | c.anchor = GridBagConstraints.WEST;
73 | c.weighty = 0;
74 | c.weightx = 1;
75 | c.insets = new Insets(0, 5, 2, 5);
76 | return c;
77 | }
78 |
79 | private void addConflictDetails() {
80 | if (change != null) {
81 | Set changes = change.getConflictingChanges().stream().map(id -> diff.getChange(id)).collect(Collectors.toSet());
82 | if (!changes.isEmpty()) {
83 | Set before = new HashSet<>(), after = new HashSet<>();
84 | for (Change change : changes) {
85 | if (change.getCommitMetadata().getDate().before(this.change.getCommitMetadata().getDate())) {
86 | before.add(change);
87 | } else {
88 | after.add(change);
89 | }
90 | }
91 | GridBagConstraints bpc = createGridBagConstraints(), apc = createGridBagConstraints();
92 | String priorConflictsPanelHeader = "Prior commits:", subsequentConflictsPanelHeader = "Subsequent commits:";
93 | if (!before.isEmpty() && !after.isEmpty()) {
94 | JScrollPane beforePnlScrollPane = getConflictsScrollPane(before, bpc, priorConflictsPanelHeader);
95 | JScrollPane afterPnlScrollPane = getConflictsScrollPane(after, apc, subsequentConflictsPanelHeader);
96 | JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, beforePnlScrollPane, afterPnlScrollPane);
97 | splitPane.setBorder(GuiUtils.EMPTY_BORDER);
98 | add(splitPane);
99 | splitPane.setDividerLocation(0.5);
100 | splitPane.setResizeWeight(0.5);
101 | } else if (!before.isEmpty()) {
102 | add(getConflictsScrollPane(before, bpc, priorConflictsPanelHeader), BorderLayout.CENTER);
103 | } else if (!after.isEmpty()) {
104 | add(getConflictsScrollPane(after, apc, subsequentConflictsPanelHeader), BorderLayout.CENTER);
105 | }
106 | }
107 | else {
108 | add(createHeaderLabel("No conflicts", Optional.of(new EmptyBorder(5, 6, 0, 0))), BorderLayout.NORTH);
109 | }
110 | repaint();
111 | }
112 | }
113 |
114 | private JScrollPane getConflictsScrollPane(Set changes, GridBagConstraints constraints, String panelHeader) {
115 | JPanel panel = new JPanel(new GridBagLayout());
116 | createSubPanel(panel, changes, constraints, panelHeader);
117 | JScrollPane scrollPane = new JScrollPane(panel);
118 | scrollPane.setBorder(GuiUtils.EMPTY_BORDER);
119 | return scrollPane;
120 | }
121 |
122 | private JLabel createHeaderLabel(String panelHeader, Optional border) {
123 | JLabel label = new JLabel(panelHeader);
124 | label.setFont(getFont().deriveFont(Font.BOLD));
125 | if(border.isPresent()) {
126 | label.setBorder(border.get());
127 | }
128 | return label;
129 | }
130 |
131 | private void createSubPanel(JPanel parent, Set changes, GridBagConstraints con, String panelHeader) {
132 | parent.add(createHeaderLabel(panelHeader, Optional.empty()), con);
133 | con.gridy = con.gridy + 1;
134 | parent.add(new JSeparator(SwingConstants.HORIZONTAL), con);
135 | con.gridy = con.gridy + 1;
136 |
137 | parent.setAlignmentX(LEFT_ALIGNMENT);
138 | parent.setBackground(GuiUtils.WHITE_BACKGROUND);
139 | parent.setBorder(new EmptyBorder(5, 1, 1, 1));
140 | if (!changes.isEmpty()) {
141 | createConflictsPanel(parent, changes, con);
142 | }
143 | // fill the remaining panel if necessary
144 | con.weightx = 1;
145 | con.weighty = 1;
146 | con.fill = GridBagConstraints.BOTH;
147 | parent.add(new JLabel(), con);
148 | }
149 |
150 | private void createConflictsPanel(JPanel panel, Set changes, GridBagConstraints con) {
151 | Map> map = new HashMap<>();
152 | for (Change change : changes) {
153 | CommitMetadata metadata = change.getCommitMetadata();
154 | if (map.containsKey(metadata)) {
155 | Set ontChanges = map.get(metadata);
156 | ontChanges.addAll(change.getChanges());
157 | map.put(metadata, ontChanges);
158 | } else {
159 | map.put(metadata, change.getChanges());
160 | }
161 | }
162 | int counter = 1;
163 | for (CommitMetadata cd : map.keySet()) {
164 | Set ontChanges = map.get(cd);
165 | ConflictingCommitPanel commitPanel = new ConflictingCommitPanel(editorKit, ontChanges, cd.getDate(), cd.getAuthor(), cd.getComment(), counter);
166 | panel.add(commitPanel, con);
167 | con.gridy = con.gridy + 1;
168 |
169 | panel.add(new JSeparator(SwingConstants.HORIZONTAL), con);
170 | con.gridy = con.gridy + 1;
171 | counter++;
172 | }
173 | }
174 |
175 | @Override
176 | public void dispose() {
177 | diffManager.removeListener(diffListener);
178 | }
179 | }
180 |
--------------------------------------------------------------------------------