├── .travis.yml ├── src └── main │ ├── resources │ ├── tip.png │ ├── commit.png │ ├── cross.png │ ├── string.png │ ├── user.png │ ├── users.png │ ├── warning.png │ ├── review-log.png │ ├── review-new.png │ ├── review-clear.png │ ├── review-commit.png │ ├── review-accepted.png │ ├── review-download.png │ ├── review-pending.png │ ├── review-rejected.png │ ├── viewconfig.xml │ └── plugin.xml │ └── java │ └── org │ └── protege │ └── editor │ └── owl │ └── client │ ├── diff │ ├── model │ │ ├── ReviewStatus.java │ │ ├── LogDiffListener.java │ │ ├── LogDiffEvent.java │ │ ├── ChangeId.java │ │ ├── RevisionTag.java │ │ ├── CommitId.java │ │ ├── ChangeMode.java │ │ ├── ConflictDetector.java │ │ ├── ChangeType.java │ │ ├── CommitMetadata.java │ │ ├── BuiltInChangeType.java │ │ ├── ChangeIdImpl.java │ │ ├── CommitIdImpl.java │ │ ├── RevisionTagImpl.java │ │ ├── OwlOntologyChangeAnnotator.java │ │ ├── ChangeDetails.java │ │ ├── ReviewManager.java │ │ ├── CustomChangeType.java │ │ ├── Review.java │ │ ├── CommitMetadataImpl.java │ │ ├── ChangeDetailsImpl.java │ │ ├── ReviewImpl.java │ │ ├── Change.java │ │ ├── SimpleConflictDetector.java │ │ ├── AxiomChangeAnnotator.java │ │ ├── ReviewManagerImpl.java │ │ └── ChangeImpl.java │ ├── ui │ │ ├── DisabledListItemSelectionModel.java │ │ ├── ChangeDetailsTableModel.java │ │ ├── CommitView.java │ │ ├── AuthorView.java │ │ ├── ChangeDetailsView.java │ │ ├── ConflictsGridView.java │ │ ├── ConflictsListView.java │ │ ├── LogDiffCellRenderer.java │ │ ├── ChangeDetailsTable.java │ │ ├── ChangesView.java │ │ ├── ChangesTable.java │ │ ├── AuthorListCellRenderer.java │ │ ├── CommitListCellRenderer.java │ │ ├── OwlCellRenderer.java │ │ ├── MultipleChangeDetailsTableModel.java │ │ ├── MatchingChangeDetailsTableModel.java │ │ ├── ConflictingCommitPanel.java │ │ ├── ChangeListCellRenderer.java │ │ ├── CommitPanel.java │ │ ├── GuiUtils.java │ │ ├── OwlObjectList.java │ │ ├── ChangeDetailsTableCellRenderer.java │ │ ├── ChangesTableModel.java │ │ ├── ChangesTableCellRenderer.java │ │ ├── AuthorPanel.java │ │ ├── ChangesPanel.java │ │ ├── ChangeDetailsPanel.java │ │ ├── ConflictsListPanel.java │ │ └── ConflictsGridPanel.java │ ├── DiffFactoryImpl.java │ └── DiffFactory.java │ ├── action │ ├── OpenFromServerAction.java │ ├── UpdateAction.java │ ├── ShowHistoryAction.java │ ├── EnableAutoUpdateAction.java │ ├── ClientStatusTableModel.java │ ├── ShowUncommittedChangesAction.java │ ├── ShowStatusAction.java │ └── CommitAction.java │ ├── panel │ ├── FormatRenderer.java │ ├── HistoryTableModel.java │ ├── ServerTableModel.java │ ├── ChangeListTableModel.java │ └── ChangeHistoryPanel.java │ ├── connect │ ├── RMIClientFactory.java │ └── ServerConnectionManager.java │ └── ClientPreferences.java ├── .gitignore ├── README.md └── pom.xml /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | script: mvn verify 5 | sudo: false 6 | -------------------------------------------------------------------------------- /src/main/resources/tip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/tip.png -------------------------------------------------------------------------------- /src/main/resources/commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/commit.png -------------------------------------------------------------------------------- /src/main/resources/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/cross.png -------------------------------------------------------------------------------- /src/main/resources/string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/string.png -------------------------------------------------------------------------------- /src/main/resources/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/user.png -------------------------------------------------------------------------------- /src/main/resources/users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/users.png -------------------------------------------------------------------------------- /src/main/resources/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/warning.png -------------------------------------------------------------------------------- /src/main/resources/review-log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/review-log.png -------------------------------------------------------------------------------- /src/main/resources/review-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/review-new.png -------------------------------------------------------------------------------- /src/main/resources/review-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/review-clear.png -------------------------------------------------------------------------------- /src/main/resources/review-commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/review-commit.png -------------------------------------------------------------------------------- /src/main/resources/review-accepted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/review-accepted.png -------------------------------------------------------------------------------- /src/main/resources/review-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/review-download.png -------------------------------------------------------------------------------- /src/main/resources/review-pending.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/review-pending.png -------------------------------------------------------------------------------- /src/main/resources/review-rejected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/protegeproject/protege-client/HEAD/src/main/resources/review-rejected.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven 2 | target/ 3 | 4 | # Eclipse 5 | .classpath 6 | .project 7 | .settings/ 8 | META-INF/ 9 | build.properties 10 | plugin.xml 11 | 12 | #intelliJ 13 | *.iws 14 | *.ipr 15 | .idea 16 | *.iml 17 | build/ 18 | 19 | src/main/java/test/* 20 | 21 | *.uml 22 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ReviewStatus.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | /** 4 | * @author Rafael Gonçalves
5 | * Stanford Center for Biomedical Informatics Research 6 | */ 7 | public enum ReviewStatus { 8 | ACCEPTED, REJECTED, PENDING 9 | } -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/LogDiffListener.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | /** 4 | * @author Rafael Gonçalves
5 | * Stanford Center for Biomedical Informatics Research 6 | */ 7 | public interface LogDiffListener { 8 | 9 | void statusChanged(LogDiffEvent event); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/LogDiffEvent.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | /** 4 | * @author Rafael Gonçalves
5 | * Stanford Center for Biomedical Informatics Research 6 | */ 7 | public enum LogDiffEvent { 8 | AUTHOR_SELECTION_CHANGED, COMMIT_SELECTION_CHANGED, CHANGE_SELECTION_CHANGED, ONTOLOGY_UPDATED, CHANGE_REVIEWED, RESET 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ChangeId.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | /** 4 | * @author Rafael Gonçalves
5 | * Stanford Center for Biomedical Informatics Research 6 | */ 7 | public interface ChangeId { 8 | 9 | /** 10 | * Get identifier 11 | * 12 | * @return Change identifier 13 | */ 14 | String get(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/RevisionTag.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | /** 4 | * @author Rafael Gonçalves
5 | * Stanford Center for Biomedical Informatics Research 6 | */ 7 | public interface RevisionTag { 8 | 9 | /** 10 | * Get the revision tag 11 | * 12 | * @return Tag 13 | */ 14 | String getTag(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/CommitId.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | /** 4 | * @author Rafael Gonçalves
5 | * Stanford Center for Biomedical Informatics Research 6 | */ 7 | public interface CommitId { 8 | 9 | /** 10 | * Get the commit identifier 11 | * 12 | * @return Commit identifier 13 | */ 14 | String get(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Protege Ontology Client 2 | ====================== 3 | 4 | Provides client functionality for the Protege Desktop application to connect to an [OWL Ontology Server][], allowing end users to collaboratively edit collections of OWL ontologies. 5 | 6 | [OWL Ontology Server]: http://github.com/protegeproject/org.protege.owl.server 7 | 8 | Compatible with Protege Desktop versions 5.0 and above. 9 | 10 | User docs: http://protegewiki.stanford.edu/wiki/Protege4ClientServer 11 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/DisabledListItemSelectionModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * @author Rafael Gonçalves
7 | * Stanford Center for Biomedical Informatics Research 8 | */ 9 | public class DisabledListItemSelectionModel extends DefaultListSelectionModel { 10 | 11 | @Override 12 | public void setSelectionInterval(int index0, int index1) { 13 | super.setSelectionInterval(-1, -1); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangeDetailsTableModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.client.diff.model.Change; 4 | 5 | import javax.swing.table.AbstractTableModel; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public abstract class ChangeDetailsTableModel extends AbstractTableModel { 12 | 13 | /** 14 | * Set the change for this change details table 15 | * 16 | * @param change Change 17 | */ 18 | abstract void setChange(Change change); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ChangeMode.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import static com.google.common.base.Preconditions.checkNotNull; 4 | 5 | /** 6 | * @author Rafael Gonçalves
7 | * Stanford Center for Biomedical Informatics Research 8 | */ 9 | public enum ChangeMode { 10 | ADDITION("+"), 11 | REMOVAL("-"), 12 | ALIGNED("±"), 13 | ONTOLOGY_IRI("@"), 14 | CUSTOM("*"); 15 | 16 | private String mode; 17 | 18 | ChangeMode(String mode) { 19 | this.mode = checkNotNull(mode); 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return mode; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ConflictDetector.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import java.util.Collection; 4 | import java.util.Set; 5 | 6 | /** 7 | * @author Rafael Gonçalves
8 | * Stanford Center for Biomedical Informatics Research 9 | */ 10 | public interface ConflictDetector { 11 | 12 | /** 13 | * Get the set of change identifiers within the given {@code searchSpace} changes corresponding 14 | * to changes in conflict with the specified one. 15 | * 16 | * @param seed Change 17 | * @param searchSpace Collection of changes on the same change subject as {@code seed} within which to search for conflicts 18 | * @return Set of change identifiers 19 | */ 20 | Set getConflictingChanges(Change seed, Collection searchSpace); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ChangeType.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import java.awt.*; 4 | import java.util.Optional; 5 | 6 | /** 7 | * @author Rafael Gonçalves
8 | * Stanford Center for Biomedical Informatics Research 9 | */ 10 | public interface ChangeType { 11 | 12 | /** 13 | * Get the display name of this change type 14 | * 15 | * @return Display name 16 | */ 17 | String getDisplayName(); 18 | 19 | /** 20 | * Check whether this change type is a built-in type 21 | * 22 | * @return true if type is built-in, false otherwise 23 | */ 24 | boolean isBuiltInType(); 25 | 26 | /** 27 | * Get the change color for this change type 28 | * 29 | * @return Color 30 | */ 31 | Optional getDisplayColor(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/action/OpenFromServerAction.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.action; 2 | 3 | import java.awt.event.ActionEvent; 4 | 5 | import org.protege.editor.owl.client.panel.OpenFromServerDialog; 6 | import org.protege.editor.owl.ui.action.ProtegeOWLAction; 7 | 8 | public class OpenFromServerAction extends ProtegeOWLAction { 9 | 10 | private static final long serialVersionUID = 1921872278936323557L; 11 | 12 | @Override 13 | public void initialise() throws Exception { 14 | } 15 | 16 | @Override 17 | public void dispose() throws Exception { 18 | } 19 | 20 | @Override 21 | public void actionPerformed(ActionEvent e) { 22 | OpenFromServerDialog dialog = new OpenFromServerDialog(getOWLEditorKit()); 23 | dialog.setLocationRelativeTo(getOWLWorkspace()); 24 | dialog.setVisible(true); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/CommitView.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.ui.view.AbstractOWLViewComponent; 4 | 5 | import java.awt.*; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public class CommitView extends AbstractOWLViewComponent { 12 | private static final long serialVersionUID = 8979240527400492916L; 13 | private CommitPanel commitPanel; 14 | 15 | @Override 16 | protected void initialiseOWLView() throws Exception { 17 | setLayout(new BorderLayout()); 18 | commitPanel = new CommitPanel(getOWLModelManager(), getOWLEditorKit()); 19 | add(commitPanel, BorderLayout.CENTER); 20 | } 21 | 22 | @Override 23 | protected void disposeOWLView() { 24 | commitPanel.dispose(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/AuthorView.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.ui.view.AbstractOWLViewComponent; 4 | 5 | import java.awt.*; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public class AuthorView extends AbstractOWLViewComponent { 12 | private static final long serialVersionUID = -5601683043252978396L; 13 | private AuthorPanel authorPanel; 14 | 15 | @Override 16 | protected void initialiseOWLView() throws Exception { 17 | setLayout(new BorderLayout()); 18 | authorPanel = new AuthorPanel(getOWLModelManager(), getOWLEditorKit()); 19 | add(authorPanel, BorderLayout.CENTER); 20 | } 21 | 22 | @Override 23 | protected void disposeOWLView() { 24 | authorPanel.dispose(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangeDetailsView.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.ui.view.AbstractOWLViewComponent; 4 | 5 | import java.awt.*; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public class ChangeDetailsView extends AbstractOWLViewComponent { 12 | private static final long serialVersionUID = 4203564449172661511L; 13 | private ChangeDetailsPanel detailsPanel; 14 | 15 | @Override 16 | protected void initialiseOWLView() throws Exception { 17 | setLayout(new BorderLayout()); 18 | detailsPanel = new ChangeDetailsPanel(getOWLModelManager(), getOWLEditorKit()); 19 | add(detailsPanel, BorderLayout.CENTER); 20 | } 21 | 22 | @Override 23 | protected void disposeOWLView() { 24 | detailsPanel.dispose(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ConflictsGridView.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.ui.view.AbstractOWLViewComponent; 4 | 5 | import java.awt.*; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public class ConflictsGridView extends AbstractOWLViewComponent { 12 | private static final long serialVersionUID = -108220117637124754L; 13 | private ConflictsGridPanel conflictsPanel; 14 | 15 | @Override 16 | protected void initialiseOWLView() throws Exception { 17 | setLayout(new BorderLayout()); 18 | conflictsPanel = new ConflictsGridPanel(getOWLModelManager(), getOWLEditorKit()); 19 | add(conflictsPanel, BorderLayout.CENTER); 20 | } 21 | 22 | @Override 23 | protected void disposeOWLView() { 24 | conflictsPanel.dispose(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ConflictsListView.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.ui.view.AbstractOWLViewComponent; 4 | 5 | import java.awt.*; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public class ConflictsListView extends AbstractOWLViewComponent { 12 | private static final long serialVersionUID = -2322371761068725012L; 13 | private ConflictsListPanel conflictsPanel; 14 | 15 | @Override 16 | protected void initialiseOWLView() throws Exception { 17 | setLayout(new BorderLayout()); 18 | conflictsPanel = new ConflictsListPanel(getOWLModelManager(), getOWLEditorKit()); 19 | add(conflictsPanel, BorderLayout.CENTER); 20 | } 21 | 22 | @Override 23 | protected void disposeOWLView() { 24 | conflictsPanel.dispose(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/CommitMetadata.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import org.protege.owl.server.api.UserId; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public interface CommitMetadata extends Comparable { 12 | 13 | /** 14 | * Get the commit identifier 15 | * 16 | * @return Commit identifier 17 | */ 18 | CommitId getCommitId(); 19 | 20 | /** 21 | * Get the user identifier of the commit author 22 | * 23 | * @return User identifier of commit author 24 | */ 25 | UserId getAuthor(); 26 | 27 | /** 28 | * Get the commit date 29 | * 30 | * @return Commit date 31 | */ 32 | Date getDate(); 33 | 34 | /** 35 | * Get the commit comment 36 | * 37 | * @return Commit comment 38 | */ 39 | String getComment(); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/LogDiffCellRenderer.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.OWLEditorKit; 4 | 5 | import javax.swing.*; 6 | import javax.swing.border.EmptyBorder; 7 | import javax.swing.table.TableCellRenderer; 8 | 9 | import static com.google.common.base.Preconditions.checkNotNull; 10 | 11 | /** 12 | * @author Rafael Gonçalves
13 | * Stanford Center for Biomedical Informatics Research 14 | */ 15 | public abstract class LogDiffCellRenderer extends JTextArea implements TableCellRenderer { 16 | protected TableCellRenderer owlCellRenderer; 17 | 18 | protected LogDiffCellRenderer(OWLEditorKit editorKit) { 19 | super(); 20 | owlCellRenderer = new OwlCellRenderer(checkNotNull(editorKit)); 21 | setLineWrap(true); 22 | setWrapStyleWord(true); 23 | setOpaque(true); 24 | setBorder(new EmptyBorder(1, 2, 1, 2)); 25 | setAlignmentY(CENTER_ALIGNMENT); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangeDetailsTable.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.OWLEditorKit; 4 | 5 | import javax.swing.*; 6 | import javax.swing.table.TableCellRenderer; 7 | import javax.swing.table.TableModel; 8 | import java.awt.*; 9 | 10 | /** 11 | * @author Rafael Gonçalves
12 | * Stanford Center for Biomedical Informatics Research 13 | */ 14 | public class ChangeDetailsTable extends JTable { 15 | private static final long serialVersionUID = 6346557554881882633L; 16 | 17 | public ChangeDetailsTable(TableModel model, OWLEditorKit editorKit) { 18 | TableCellRenderer renderer = new ChangeDetailsTableCellRenderer(editorKit); 19 | setModel(model); 20 | setDefaultRenderer(Object.class, renderer); 21 | setRowHeight(30); 22 | setShowGrid(false); 23 | setAlignmentY(SwingConstants.CENTER); 24 | setRowMargin(0); 25 | setIntercellSpacing(new Dimension(0, 0)); 26 | setRowSelectionAllowed(false); 27 | setCellSelectionEnabled(false); 28 | setFocusable(false); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangesView.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.ui.view.AbstractOWLViewComponent; 4 | 5 | import java.awt.*; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public class ChangesView extends AbstractOWLViewComponent { 12 | private static final long serialVersionUID = 8062695577507306066L; 13 | private ChangesPanel changesPanel; 14 | private ReviewButtonsPanel reviewButtonsPanel; 15 | 16 | @Override 17 | protected void initialiseOWLView() throws Exception { 18 | setLayout(new BorderLayout()); 19 | changesPanel = new ChangesPanel(getOWLModelManager(), getOWLEditorKit()); 20 | reviewButtonsPanel = new ReviewButtonsPanel(getOWLModelManager(), getOWLEditorKit()); 21 | add(changesPanel, BorderLayout.CENTER); 22 | add(reviewButtonsPanel, BorderLayout.SOUTH); 23 | } 24 | 25 | @Override 26 | protected void disposeOWLView() { 27 | changesPanel.dispose(); 28 | reviewButtonsPanel.dispose(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/BuiltInChangeType.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import java.awt.*; 4 | import java.util.Optional; 5 | 6 | import static com.google.common.base.Preconditions.checkNotNull; 7 | 8 | /** 9 | * @author Rafael Gonçalves
10 | * Stanford Center for Biomedical Informatics Research 11 | */ 12 | public enum BuiltInChangeType implements ChangeType { 13 | LOGICAL("Logical"), 14 | SIGNATURE("Signature"), 15 | ANNOTATION("Annotation"), 16 | IMPORT("Import"), 17 | ONTOLOGY_ANNOTATION("Ontology Annotation"), 18 | ONTOLOGY_IRI("Ontology IRI"); 19 | 20 | private String type; 21 | 22 | BuiltInChangeType(String type) { 23 | this.type = checkNotNull(type); 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return type; 29 | } 30 | 31 | @Override 32 | public String getDisplayName() { 33 | return type; 34 | } 35 | 36 | @Override 37 | public boolean isBuiltInType() { 38 | return true; 39 | } 40 | 41 | @Override 42 | public Optional getDisplayColor() { 43 | return Optional.empty(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangesTable.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.OWLEditorKit; 4 | 5 | import javax.swing.*; 6 | import javax.swing.table.TableCellRenderer; 7 | import javax.swing.table.TableModel; 8 | import java.awt.*; 9 | import java.util.Date; 10 | 11 | /** 12 | * @author Rafael Gonçalves
13 | * Stanford Center for Biomedical Informatics Research 14 | */ 15 | public class ChangesTable extends JTable { 16 | private static final long serialVersionUID = 224898759560741040L; 17 | 18 | public ChangesTable(TableModel model, OWLEditorKit editorKit) { 19 | TableCellRenderer renderer = new ChangesTableCellRenderer(editorKit); 20 | setModel(model); 21 | setDefaultRenderer(Object.class, renderer); 22 | setDefaultRenderer(Date.class, renderer); 23 | setDefaultRenderer(Boolean.class, renderer); 24 | setRowHeight(32); 25 | setShowGrid(false); 26 | setAlignmentY(SwingConstants.CENTER); 27 | setRowMargin(0); 28 | setIntercellSpacing(new Dimension(0, 0)); 29 | setRowSelectionAllowed(true); 30 | setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/AuthorListCellRenderer.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.client.diff.model.LogDiffManager; 4 | import org.protege.owl.server.api.UserId; 5 | 6 | import javax.swing.*; 7 | import javax.swing.border.EmptyBorder; 8 | import java.awt.*; 9 | 10 | /** 11 | * @author Rafael Gonçalves
12 | * Stanford Center for Biomedical Informatics Research 13 | */ 14 | public class AuthorListCellRenderer extends DefaultListCellRenderer { 15 | 16 | @Override 17 | public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 18 | JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 19 | UserId user = (UserId)value; 20 | if(user.equals(LogDiffManager.ALL_AUTHORS)) { 21 | label.setIcon(GuiUtils.getIcon(GuiUtils.USERS_ICON_FILENAME, 20, 20)); 22 | label.setFont(getFont().deriveFont(Font.BOLD)); 23 | } 24 | else { 25 | label.setIcon(GuiUtils.getIcon(GuiUtils.USER_ICON_FILENAME, 20, 20)); 26 | } 27 | label.setBorder(new EmptyBorder(0, 7, 0, 0)); 28 | label.setIconTextGap(7); 29 | return label; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ChangeIdImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | 6 | import static com.google.common.base.Preconditions.checkNotNull; 7 | 8 | /** 9 | * @author Rafael Gonçalves
10 | * Stanford Center for Biomedical Informatics Research 11 | */ 12 | public final class ChangeIdImpl implements ChangeId { 13 | private final String id; 14 | 15 | /** 16 | * Constructor 17 | * 18 | * @param id Identifier 19 | */ 20 | public ChangeIdImpl(String id) { 21 | this.id = checkNotNull(id); 22 | } 23 | 24 | @Override 25 | public String get() { 26 | return id; 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (this == o) return true; 32 | if (o == null || getClass() != o.getClass()) return false; 33 | ChangeIdImpl changeId = (ChangeIdImpl) o; 34 | return Objects.equal(id, changeId.id); 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | return Objects.hashCode(id); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return MoreObjects.toStringHelper(this) 45 | .add("id", id) 46 | .toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/CommitIdImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | 6 | import static com.google.common.base.Preconditions.checkNotNull; 7 | 8 | /** 9 | * @author Rafael Gonçalves
10 | * Stanford Center for Biomedical Informatics Research 11 | */ 12 | public final class CommitIdImpl implements CommitId { 13 | private final String id; 14 | 15 | /** 16 | * Constructor 17 | * 18 | * @param id Commit identifier 19 | */ 20 | public CommitIdImpl(String id) { 21 | this.id = checkNotNull(id); 22 | } 23 | 24 | @Override 25 | public String get() { 26 | return id; 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (this == o) return true; 32 | if (o == null || getClass() != o.getClass()) return false; 33 | CommitIdImpl commitId = (CommitIdImpl) o; 34 | return Objects.equal(id, commitId.id); 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | return Objects.hashCode(id); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return MoreObjects.toStringHelper(this) 45 | .add("id", id) 46 | .toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/RevisionTagImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | 6 | import static com.google.common.base.Preconditions.checkNotNull; 7 | 8 | /** 9 | * @author Rafael Gonçalves
10 | * Stanford Center for Biomedical Informatics Research 11 | */ 12 | public final class RevisionTagImpl implements RevisionTag { 13 | private final String tag; 14 | 15 | /** 16 | * Constructor 17 | * 18 | * @param tag Revision tag string 19 | */ 20 | public RevisionTagImpl(String tag) { 21 | this.tag = checkNotNull(tag); 22 | } 23 | 24 | @Override 25 | public String getTag() { 26 | return tag; 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (this == o) return true; 32 | if (o == null || getClass() != o.getClass()) return false; 33 | RevisionTagImpl that = (RevisionTagImpl) o; 34 | return Objects.equal(tag, that.tag); 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | return Objects.hashCode(tag); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return MoreObjects.toStringHelper(this) 45 | .add("tag", tag) 46 | .toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/CommitListCellRenderer.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.client.diff.model.CommitMetadata; 4 | 5 | import javax.swing.*; 6 | import javax.swing.border.EmptyBorder; 7 | import java.awt.*; 8 | 9 | /** 10 | * @author Rafael Gonçalves
11 | * Stanford Center for Biomedical Informatics Research 12 | */ 13 | public class CommitListCellRenderer extends DefaultListCellRenderer { 14 | 15 | @Override 16 | public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 17 | JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 18 | label.setBorder(new EmptyBorder(7, 7, 7, 3)); 19 | label.setIcon(GuiUtils.getIcon(GuiUtils.COMMIT_ICON_FILENAME, 17, 17)); 20 | label.setIconTextGap(9); 21 | 22 | CommitMetadata c = (CommitMetadata) value; 23 | label.setToolTipText("Comment: " + c.getComment()); 24 | 25 | String dateStr = GuiUtils.getShortenedFormattedDate(c.getDate()); 26 | label.setText("" + dateStr + " · " + c.getAuthor().getUserName() + 27 | "

" + c.getComment() + "

"); 28 | return label; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/OwlOntologyChangeAnnotator.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import org.semanticweb.owlapi.model.OWLEntity; 4 | import org.semanticweb.owlapi.model.OWLOntologyChange; 5 | 6 | import java.util.List; 7 | import java.util.Optional; 8 | 9 | /** 10 | * @author Rafael Gonçalves
11 | * Stanford Center for Biomedical Informatics Research 12 | */ 13 | public interface OwlOntologyChangeAnnotator { 14 | 15 | /** 16 | * Get a bundle of OWL ontology changes annotated with a structured-text value based on the given parameters. These changes are subsequently 17 | * interpreted as a single change (i.e., one row in the diff GUI) that bundles multiple OWLOntologyChange-level changes. 18 | * 19 | * @param changes List of changes to be annotated 20 | * @param revisionTag Revision tag 21 | * @param changeSubject Change subject (i.e., OWL entity) 22 | * @param changeType Change type 23 | * @param p Annotation property that got changed 24 | * @param newValue New value of the (annotation) property 25 | * @return List of annotated ontology changes 26 | */ 27 | List getAnnotatedChange(List changes, RevisionTag revisionTag, OWLEntity changeSubject, ChangeType changeType, 28 | Optional p, Optional newValue); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ChangeDetails.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import org.semanticweb.owlapi.model.OWLObject; 4 | 5 | import java.util.Optional; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public interface ChangeDetails { 12 | 13 | /** 14 | * Get the revision tag for this change 15 | * 16 | * @return Revision tag 17 | */ 18 | RevisionTag getRevisionTag(); 19 | 20 | /** 21 | * Get the change subject, that is (for most axioms), the left-hand side of the axiom. For example, 22 | * for A SubClassOf B the change subject is A. This may be an OWL entity or class expression 23 | * 24 | * @return Change subject as an OWLObject 25 | */ 26 | OWLObject getSubject(); 27 | 28 | /** 29 | * Get the change type, which could be one of the built-in types such as logical, signature or 30 | * annotation, or a custom type 31 | * 32 | * @return Change type 33 | */ 34 | ChangeType getType(); 35 | 36 | /** 37 | * Get the (annotation) property involved in the change, if any 38 | * 39 | * @return Annotation property changed 40 | */ 41 | Optional getProperty(); 42 | 43 | /** 44 | * Get the new annotation property value 45 | * 46 | * @return Annotation property assertion literal value 47 | */ 48 | Optional getNewValue(); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ReviewManager.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import org.semanticweb.owlapi.model.OWLOntologyChange; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author Rafael Gonçalves
9 | * Stanford Center for Biomedical Informatics Research 10 | */ 11 | public interface ReviewManager { 12 | 13 | /** 14 | * Set the specified review status for the given change 15 | * 16 | * @param c Change 17 | * @param status Review status 18 | */ 19 | void setReviewStatus(Change c, ReviewStatus status); 20 | 21 | /** 22 | * Check whether the review of the specified change has changed since its initial state 23 | * 24 | * @param c Change 25 | * @return true if change review has changed since its initial state, false otherwise 26 | */ 27 | boolean reviewChanged(Change c); 28 | 29 | /** 30 | * Check whether there are change reviews that have not been uncommitted 31 | * 32 | * @return true if there are uncommitted reviews, false otherwise 33 | */ 34 | boolean hasUncommittedReviews(); 35 | 36 | /** 37 | * Get the list of ontology changes derived from the uncommitted reviews 38 | * 39 | * @return List of OWL ontology changes derived from uncommitted reviews 40 | */ 41 | List getReviewOntologyChanges(); 42 | 43 | /** 44 | * Clear any uncommitted reviews (and set their review status to pending) 45 | */ 46 | void clearUncommittedReviews(); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/panel/FormatRenderer.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.panel; 2 | 3 | import org.protege.editor.core.ui.error.ErrorLogPanel; 4 | 5 | import javax.swing.table.DefaultTableCellRenderer; 6 | import java.text.DateFormat; 7 | import java.text.Format; 8 | 9 | /* 10 | * Code from: http://tips4java.wordpress.com/2008/10/11/table-format-renderers/ 11 | */ 12 | public class FormatRenderer extends DefaultTableCellRenderer { 13 | 14 | private static final long serialVersionUID = -5210230827997957826L; 15 | private Format formatter; 16 | 17 | /* 18 | * Use the specified formatter to format the Object 19 | */ 20 | public FormatRenderer(Format formatter) { 21 | this.formatter = formatter; 22 | } 23 | 24 | public void setValue(Object value) { 25 | // Format the Object before setting its value in the renderer 26 | try { 27 | if (value != null) { 28 | value = formatter.format(value); 29 | } 30 | } 31 | catch(IllegalArgumentException e) { 32 | ErrorLogPanel.showErrorDialog(e); 33 | } 34 | 35 | super.setValue(value); 36 | } 37 | 38 | /* 39 | * Use the default date/time formatter for the default locale 40 | */ 41 | public static FormatRenderer getDateTimeRenderer() { 42 | return new FormatRenderer(DateFormat.getDateTimeInstance()); 43 | } 44 | 45 | /* 46 | * Use the default time formatter for the default locale 47 | */ 48 | public static FormatRenderer getTimeRenderer() { 49 | return new FormatRenderer(DateFormat.getTimeInstance()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/connect/RMIClientFactory.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.connect; 2 | 3 | import java.awt.Component; 4 | import java.rmi.NotBoundException; 5 | import java.rmi.RemoteException; 6 | 7 | import org.protege.editor.owl.client.panel.LoginDialog; 8 | import org.protege.owl.server.api.AuthToken; 9 | import org.protege.owl.server.api.exception.AuthenticationFailedException; 10 | import org.protege.owl.server.api.exception.UserDeclinedAuthenticationException; 11 | import org.protege.owl.server.connect.rmi.AbstractRMIClientFactory; 12 | import org.semanticweb.owlapi.model.IRI; 13 | 14 | public class RMIClientFactory extends AbstractRMIClientFactory { 15 | Component parent = null; 16 | 17 | public RMIClientFactory(Component parent) { 18 | this.parent = parent; 19 | } 20 | 21 | @Override 22 | protected AuthToken login(IRI serverLocation) throws AuthenticationFailedException { 23 | AuthToken token = null; 24 | 25 | LoginDialog login = new LoginDialog(); 26 | login.setLocationRelativeTo(parent); 27 | login.showDialog(); 28 | 29 | if (login.okPressed()) { 30 | try { 31 | token = login(serverLocation, login.getName(), login.getPass()); 32 | } 33 | catch (RemoteException e) { 34 | throw new AuthenticationFailedException(e); 35 | } 36 | catch (NotBoundException nbe) { 37 | throw new AuthenticationFailedException(nbe); 38 | } 39 | } 40 | else { 41 | throw new UserDeclinedAuthenticationException("User pressed the cancel button."); 42 | } 43 | return token; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/resources/viewconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/CustomChangeType.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.Objects; 4 | 5 | import java.awt.*; 6 | import java.util.Optional; 7 | 8 | import static com.google.common.base.Preconditions.checkNotNull; 9 | 10 | /** 11 | * @author Rafael Gonçalves
12 | * Stanford Center for Biomedical Informatics Research 13 | */ 14 | public final class CustomChangeType implements ChangeType { 15 | private final String displayName; 16 | private final Color color; 17 | 18 | /** 19 | * Constructor 20 | * 21 | * @param displayName Change type display name 22 | * @param color Change type display color 23 | */ 24 | public CustomChangeType(String displayName, Optional color) { 25 | this.displayName = checkNotNull(displayName); 26 | this.color = (color.isPresent() ? checkNotNull(color.get()) : null); 27 | } 28 | 29 | @Override 30 | public String getDisplayName() { 31 | return displayName; 32 | } 33 | 34 | @Override 35 | public boolean isBuiltInType() { 36 | return false; 37 | } 38 | 39 | @Override 40 | public Optional getDisplayColor() { 41 | return Optional.ofNullable(color); 42 | } 43 | 44 | 45 | @Override 46 | public boolean equals(Object o) { 47 | if (this == o) return true; 48 | if (o == null || getClass() != o.getClass()) return false; 49 | CustomChangeType that = (CustomChangeType) o; 50 | return Objects.equal(displayName, that.displayName) && 51 | Objects.equal(color, that.color); 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return Objects.hashCode(displayName, color); 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return displayName; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/OwlCellRenderer.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.OWLEditorKit; 4 | import org.protege.editor.owl.ui.OWLIcons; 5 | import org.protege.editor.owl.ui.renderer.OWLAnnotationPropertyIcon; 6 | import org.protege.editor.owl.ui.renderer.OWLCellRenderer; 7 | import org.semanticweb.owlapi.model.IRI; 8 | import org.semanticweb.owlapi.model.OWLObject; 9 | 10 | import javax.swing.*; 11 | 12 | /** 13 | * @author Rafael Gonçalves
14 | * Stanford Center for Biomedical Informatics Research 15 | */ 16 | public class OwlCellRenderer extends OWLCellRenderer { 17 | private OWLEditorKit editorKit; 18 | 19 | public OwlCellRenderer(OWLEditorKit editorKit) { 20 | this(editorKit, true, true); 21 | } 22 | 23 | public OwlCellRenderer(OWLEditorKit editorKit, boolean renderExpression, boolean renderIcon) { 24 | super(editorKit, renderExpression, renderIcon); 25 | this.editorKit = editorKit; 26 | setOpaque(true); 27 | setHighlightKeywords(true); 28 | } 29 | 30 | @Override 31 | protected Icon getIcon(Object object) { 32 | if(object instanceof IRI) { 33 | setHighlightKeywords(false); 34 | IRI ontIri = editorKit.getOWLModelManager().getActiveOntology().getOntologyID().getOntologyIRI().get(); 35 | if(!object.equals(ontIri)) { // IRI of OWLAnnotationSubject 36 | return new OWLAnnotationPropertyIcon(); 37 | } 38 | else { // IRI of ontology 39 | return OWLIcons.getIcon(GuiUtils.ONTOLOGY_ICON_FILENAME); 40 | } 41 | } 42 | else if(object instanceof String) { 43 | setHighlightKeywords(false); 44 | return GuiUtils.getIcon(GuiUtils.STRING_ICON_FILENAME, 13, 13); 45 | } 46 | else { 47 | return editorKit.getWorkspace().getOWLIconProvider().getIcon((OWLObject) object); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/Review.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import org.protege.owl.server.api.UserId; 4 | 5 | import java.util.Date; 6 | import java.util.Optional; 7 | 8 | /** 9 | * @author Rafael Gonçalves
10 | * Stanford Center for Biomedical Informatics Research 11 | */ 12 | public interface Review { 13 | 14 | /** 15 | * Get the change review status, i.e., whether a change is accepted, rejected or pending review 16 | * 17 | * @return Review status 18 | */ 19 | ReviewStatus getStatus(); 20 | 21 | /** 22 | * Get the identifier of the author of the review 23 | * 24 | * @return User identifier 25 | */ 26 | Optional getAuthor(); 27 | 28 | /** 29 | * Get the date of the review 30 | * 31 | * @return Review date 32 | */ 33 | Optional getDate(); 34 | 35 | /** 36 | * Get the review comment 37 | * 38 | * @return Review comment 39 | */ 40 | Optional getComment(); 41 | 42 | /** 43 | * Check whether the review has been committed to the server 44 | * 45 | * @return true if review is committed to the server, false otherwise 46 | */ 47 | boolean isCommitted(); 48 | 49 | /** 50 | * Set the author of the review by its user identifier 51 | * 52 | * @param author User identifier of review author 53 | */ 54 | void setAuthor(UserId author); 55 | 56 | /** 57 | * Set the date of the review 58 | * 59 | * @param date Review date 60 | */ 61 | void setDate(Date date); 62 | 63 | /** 64 | * Set the status of the review 65 | * 66 | * @param status Review status 67 | */ 68 | void setStatus(ReviewStatus status); 69 | 70 | /** 71 | * Set the comment of review 72 | * 73 | * @param comment Review comment 74 | */ 75 | void setComment(String comment); 76 | 77 | /** 78 | * Set whether the review has been committed to the server 79 | * 80 | * @param committed true if review is committed, false otherwise 81 | */ 82 | void setCommitted(boolean committed); 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/ClientPreferences.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.protege.editor.core.prefs.Preferences; 7 | import org.protege.editor.core.prefs.PreferencesManager; 8 | 9 | public class ClientPreferences { 10 | 11 | private static ClientPreferences instance; 12 | 13 | private static final String CLIENT_PREFERENCES = "org.protege.editor.owl.client"; 14 | 15 | private static final String CURRENT_USERNAME = "CURRENT_USERNAME"; 16 | 17 | private static final String SERVER_LOCATIONS = "SERVER_LOCATIONS"; 18 | 19 | private static final String LAST_SERVER_LOCATION = "LAST_SERVER_LOCATION"; 20 | 21 | public static synchronized ClientPreferences getInstance() { 22 | if(instance == null) { 23 | instance = new ClientPreferences(); 24 | } 25 | return instance; 26 | } 27 | 28 | public String getCurrentUsername() { 29 | Preferences prefs = getPreferences(); 30 | return prefs.getString(CURRENT_USERNAME, null); 31 | } 32 | 33 | public void setCurrentUsername(String username) { 34 | Preferences prefs = getPreferences(); 35 | prefs.putString(CURRENT_USERNAME, username); 36 | } 37 | 38 | public List getServerLocations() { 39 | ArrayList serverLocations = new ArrayList(); 40 | serverLocations.addAll(getPreferences().getStringList(SERVER_LOCATIONS, new ArrayList())); 41 | return serverLocations; 42 | } 43 | 44 | public void setServerLocations(ArrayList serverLocations) { 45 | Preferences prefs = getPreferences(); 46 | prefs.putStringList(SERVER_LOCATIONS, serverLocations); 47 | } 48 | 49 | public String getLastServerLocation() { 50 | Preferences prefs = getPreferences(); 51 | return prefs.getString(LAST_SERVER_LOCATION, null); 52 | } 53 | 54 | public void setLastServerLocation(String lastServerLocation) { 55 | Preferences prefs = getPreferences(); 56 | prefs.putString(LAST_SERVER_LOCATION, lastServerLocation); 57 | } 58 | 59 | protected static Preferences getPreferences() { 60 | return PreferencesManager.getInstance().getApplicationPreferences(CLIENT_PREFERENCES); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/MultipleChangeDetailsTableModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.client.diff.model.Change; 4 | import org.semanticweb.owlapi.model.OWLOntologyChange; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import static com.google.common.base.Preconditions.checkNotNull; 10 | 11 | /** 12 | * @author Rafael Gonçalves
13 | * Stanford Center for Biomedical Informatics Research 14 | */ 15 | public class MultipleChangeDetailsTableModel extends ChangeDetailsTableModel { 16 | private static final long serialVersionUID = 4589232596919944476L; 17 | private List changes; 18 | 19 | /** 20 | * No-args constructor 21 | */ 22 | public MultipleChangeDetailsTableModel() { } 23 | 24 | @Override 25 | public void setChange(Change change) { 26 | checkNotNull(change); 27 | this.changes = new ArrayList<>(change.getChanges()); 28 | fireTableDataChanged(); 29 | } 30 | 31 | @Override 32 | public int getRowCount() { 33 | return (changes != null ? changes.size() : 0); 34 | } 35 | 36 | @Override 37 | public int getColumnCount() { 38 | return Column.values().length; 39 | } 40 | 41 | @Override 42 | public Object getValueAt(int rowIndex, int columnIndex) { 43 | return changes.get(rowIndex); 44 | } 45 | 46 | @Override 47 | public Class getColumnClass(int columnIndex) { 48 | Column col = Column.values()[columnIndex]; 49 | switch (col) { 50 | case CHANGES: 51 | return OWLOntologyChange.class; 52 | default: 53 | throw new IllegalStateException("Programmer Error: a case was missed"); 54 | } 55 | } 56 | 57 | @Override 58 | public String getColumnName(int column) { 59 | return Column.values()[column].toString(); 60 | } 61 | 62 | public enum Column { 63 | CHANGES("Change(s)"); 64 | 65 | private String name; 66 | 67 | Column(String name) { 68 | this.name = checkNotNull(name); 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return name; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/action/UpdateAction.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.action; 2 | 3 | import org.protege.editor.core.ui.error.ErrorLogPanel; 4 | import org.protege.editor.owl.client.connect.ServerConnectionManager; 5 | import org.protege.editor.owl.ui.action.ProtegeOWLAction; 6 | import org.protege.owl.server.api.client.Client; 7 | import org.protege.owl.server.api.client.VersionedOntologyDocument; 8 | import org.protege.owl.server.api.exception.OWLServerException; 9 | import org.protege.owl.server.util.ClientUtilities; 10 | import org.semanticweb.owlapi.model.OWLOntology; 11 | 12 | import javax.swing.*; 13 | import java.awt.*; 14 | import java.awt.event.ActionEvent; 15 | import java.util.concurrent.Future; 16 | 17 | public class UpdateAction extends ProtegeOWLAction { 18 | 19 | private static final long serialVersionUID = 2694484296709954780L; 20 | private ServerConnectionManager connectionManager; 21 | 22 | @Override 23 | public void initialise() throws Exception { 24 | connectionManager = ServerConnectionManager.get(getOWLEditorKit()); 25 | } 26 | 27 | @Override 28 | public void dispose() throws Exception { 29 | 30 | } 31 | 32 | @Override 33 | public void actionPerformed(ActionEvent e) { 34 | Container owner = SwingUtilities.getAncestorOfClass(Frame.class,getOWLWorkspace()); 35 | OWLOntology ontology = getOWLModelManager().getActiveOntology(); 36 | VersionedOntologyDocument vont = connectionManager.getVersionedOntology(ontology); 37 | if (vont == null) { 38 | JOptionPane.showMessageDialog(owner, "Update ignored because the ontology is not associated with a server."); 39 | return; 40 | } 41 | @SuppressWarnings("unused") 42 | Future ret = connectionManager.getSingleThreadExecutorService().submit(new DoUpdate(vont)); 43 | // if you wait here with ret.get(), then Protege will deadlock because he needs the UI thread to modify the ontology. 44 | } 45 | 46 | private class DoUpdate implements Runnable { 47 | private VersionedOntologyDocument vont; 48 | 49 | public DoUpdate(VersionedOntologyDocument vont) { 50 | this.vont = vont; 51 | } 52 | 53 | @Override 54 | public void run() { 55 | try { 56 | OWLOntology ontology = vont.getOntology(); 57 | Client client = connectionManager.createClient(ontology); 58 | ClientUtilities.update(client, vont); 59 | } 60 | catch (OWLServerException ioe) { 61 | ErrorLogPanel.showErrorDialog(ioe); 62 | } 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/action/ShowHistoryAction.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.action; 2 | 3 | import org.protege.editor.core.ui.error.ErrorLogPanel; 4 | import org.protege.editor.owl.client.connect.ServerConnectionManager; 5 | import org.protege.editor.owl.client.panel.ChangeHistoryPanel; 6 | import org.protege.editor.owl.ui.action.ProtegeOWLAction; 7 | import org.protege.owl.server.api.ChangeHistory; 8 | import org.protege.owl.server.api.OntologyDocumentRevision; 9 | import org.protege.owl.server.api.RevisionPointer; 10 | import org.protege.owl.server.api.client.Client; 11 | import org.protege.owl.server.api.client.VersionedOntologyDocument; 12 | import org.protege.owl.server.api.exception.UserDeclinedAuthenticationException; 13 | import org.protege.owl.server.util.ClientUtilities; 14 | import org.semanticweb.owlapi.model.OWLOntology; 15 | 16 | import javax.swing.*; 17 | import java.awt.event.ActionEvent; 18 | 19 | public class ShowHistoryAction extends ProtegeOWLAction { 20 | private static final long serialVersionUID = -7628375950917155764L; 21 | 22 | @Override 23 | public void initialise() throws Exception { 24 | 25 | } 26 | 27 | @Override 28 | public void dispose() throws Exception { 29 | 30 | } 31 | 32 | @Override 33 | public void actionPerformed(ActionEvent arg0) { 34 | try { 35 | ServerConnectionManager connectionManager = ServerConnectionManager.get(getOWLEditorKit()); 36 | OWLOntology ontology = getOWLModelManager().getActiveOntology(); 37 | VersionedOntologyDocument vont = connectionManager.getVersionedOntology(ontology); 38 | Client client = connectionManager.createClient(ontology); 39 | if (vont != null) { 40 | ChangeHistory changes = ClientUtilities.getChanges(client, vont, OntologyDocumentRevision.START_REVISION.asPointer(), RevisionPointer.HEAD_REVISION); 41 | ChangeHistoryPanel changeHistoryPanel = new ChangeHistoryPanel(getOWLEditorKit(), changes); 42 | changeHistoryPanel.setLocationRelativeTo(getOWLWorkspace()); 43 | changeHistoryPanel.setVisible(true); 44 | } 45 | else { 46 | JOptionPane.showMessageDialog(getOWLWorkspace(), "Active ontology is not connected to a server."); 47 | } 48 | } 49 | catch (UserDeclinedAuthenticationException udae) { 50 | ; // ignore this because the user knows that he didn't authenticate 51 | } 52 | catch (Exception e) { 53 | ErrorLogPanel.showErrorDialog(e); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/MatchingChangeDetailsTableModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.client.diff.model.Change; 4 | import org.semanticweb.owlapi.model.OWLOntologyChange; 5 | 6 | import static com.google.common.base.Preconditions.checkNotNull; 7 | 8 | /** 9 | * @author Rafael Gonçalves
10 | * Stanford Center for Biomedical Informatics Research 11 | */ 12 | public class MatchingChangeDetailsTableModel extends ChangeDetailsTableModel { 13 | private static final long serialVersionUID = 5697537763526759029L; 14 | private OWLOntologyChange baselineChange, newChange; 15 | 16 | /** 17 | * No-args constructor 18 | */ 19 | public MatchingChangeDetailsTableModel() { } 20 | 21 | @Override 22 | public void setChange(Change change) { 23 | checkNotNull(change); 24 | baselineChange = checkNotNull(change.getBaselineChange().get()); 25 | newChange = change.getChanges().iterator().next(); // there should only be one ontology change 26 | fireTableDataChanged(); 27 | } 28 | 29 | @Override 30 | public int getRowCount() { 31 | return (newChange != null && baselineChange != null ? 1 : 0); 32 | } 33 | 34 | @Override 35 | public int getColumnCount() { 36 | return Column.values().length; 37 | } 38 | 39 | @Override 40 | public Object getValueAt(int rowIndex, int columnIndex) { 41 | if(getColumnName(columnIndex).equals(Column.BASELINE.toString())) { 42 | return baselineChange; 43 | } 44 | else if(getColumnName(columnIndex).equals(Column.NEW.toString())) { 45 | return newChange; 46 | } 47 | else { 48 | throw new IllegalStateException("Column does not exist"); 49 | } 50 | } 51 | 52 | @Override 53 | public Class getColumnClass(int columnIndex) { 54 | Column col = Column.values()[columnIndex]; 55 | switch (col) { 56 | case NEW: 57 | case BASELINE: 58 | return OWLOntologyChange.class; 59 | default: 60 | throw new IllegalStateException("Programmer Error: a case was missed"); 61 | } 62 | } 63 | 64 | @Override 65 | public String getColumnName(int column) { 66 | return Column.values()[column].toString(); 67 | } 68 | 69 | public enum Column { 70 | BASELINE("Baseline"), 71 | NEW("New"); 72 | 73 | private String name; 74 | 75 | Column(String name) { 76 | this.name = checkNotNull(name); 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return name; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/CommitMetadataImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | import org.protege.owl.server.api.UserId; 6 | 7 | import java.util.Date; 8 | 9 | import static com.google.common.base.Preconditions.checkNotNull; 10 | 11 | /** 12 | * @author Rafael Gonçalves
13 | * Stanford Center for Biomedical Informatics Research 14 | */ 15 | public final class CommitMetadataImpl implements CommitMetadata { 16 | private final CommitId commitId; 17 | private final UserId userId; 18 | private final Date date; 19 | private final String comment; 20 | 21 | /** 22 | * Constructor 23 | * 24 | * @param commitId Commit identifier 25 | * @param userId User identifier 26 | * @param date Commit date 27 | * @param comment Commit comment 28 | */ 29 | public CommitMetadataImpl(CommitId commitId, UserId userId, Date date, String comment) { 30 | this.commitId = checkNotNull(commitId); 31 | this.userId = checkNotNull(userId); 32 | this.date = checkNotNull(date); 33 | this.comment = checkNotNull(comment); 34 | } 35 | 36 | @Override 37 | public CommitId getCommitId() { 38 | return commitId; 39 | } 40 | 41 | @Override 42 | public UserId getAuthor() { 43 | return userId; 44 | } 45 | 46 | @Override 47 | public Date getDate() { 48 | return date; 49 | } 50 | 51 | @Override 52 | public String getComment() { 53 | return comment; 54 | } 55 | 56 | @Override 57 | public boolean equals(Object o) { 58 | if (this == o) return true; 59 | if (o == null || getClass() != o.getClass()) return false; 60 | CommitMetadataImpl commit = (CommitMetadataImpl) o; 61 | return Objects.equal(commitId, commit.commitId) && 62 | Objects.equal(userId, commit.userId) && 63 | Objects.equal(date, commit.date) && 64 | Objects.equal(comment, commit.comment); 65 | } 66 | 67 | @Override 68 | public int hashCode() { 69 | return Objects.hashCode(commitId, userId, date, comment); 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return MoreObjects.toStringHelper(this) 75 | .add("commitId", commitId) 76 | .add("userId", userId) 77 | .add("date", date) 78 | .add("comment", comment) 79 | .toString(); 80 | } 81 | 82 | @Override 83 | public int compareTo(CommitMetadata that) { 84 | return that.getDate().compareTo(this.date); // compare w.r.t. date only 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/panel/HistoryTableModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.panel; 2 | 3 | import java.util.Date; 4 | 5 | import javax.swing.table.AbstractTableModel; 6 | 7 | import org.protege.owl.server.api.ChangeHistory; 8 | import org.protege.owl.server.api.ChangeMetaData; 9 | 10 | public class HistoryTableModel extends AbstractTableModel { 11 | private static final long serialVersionUID = -1510343786742688724L; 12 | 13 | public enum Column { 14 | DATE("Date", Date.class) { 15 | @Override 16 | public Date getValue(ChangeMetaData metaData) { 17 | return metaData.getDate(); 18 | } 19 | }, 20 | USER("Author", String.class) { 21 | @Override 22 | public String getValue(ChangeMetaData metaData) { 23 | return metaData.getUserId().getUserName(); 24 | } 25 | }, 26 | COMMIT_COMMENT("Comment", String.class) { 27 | @Override 28 | public String getValue(ChangeMetaData metaData) { 29 | return metaData.getCommitComment(); 30 | } 31 | }; 32 | 33 | private String name; 34 | private Class clazz; 35 | 36 | 37 | private Column(String name, Class clazz) { 38 | this.name = name; 39 | this.clazz = clazz; 40 | } 41 | 42 | public String getName() { 43 | return name; 44 | } 45 | 46 | public Class getClazz() { 47 | return clazz; 48 | } 49 | 50 | public abstract Object getValue(ChangeMetaData metaData); 51 | 52 | } 53 | private ChangeHistory changes; 54 | 55 | public HistoryTableModel(ChangeHistory changes) { 56 | this.changes = changes; 57 | } 58 | 59 | @Override 60 | public int getRowCount() { 61 | return changes.getEndRevision().getRevisionDifferenceFrom(changes.getStartRevision()); 62 | } 63 | 64 | @Override 65 | public int getColumnCount() { 66 | return Column.values().length; 67 | } 68 | 69 | @Override 70 | public Class getColumnClass(int columnIndex) { 71 | Column col = Column.values()[columnIndex]; 72 | return col.getClazz(); 73 | } 74 | 75 | @Override 76 | public String getColumnName(int column) { 77 | Column col = Column.values()[column]; 78 | return col.getName(); 79 | } 80 | 81 | @Override 82 | public Object getValueAt(int rowIndex, int columnIndex) { 83 | Column col = Column.values()[columnIndex]; 84 | ChangeMetaData metaData = changes.getMetaData(changes.getStartRevision().add(rowIndex)); 85 | return col.getValue(metaData); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/DiffFactoryImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff; 2 | 3 | import com.fasterxml.uuid.EthernetAddress; 4 | import com.fasterxml.uuid.Generators; 5 | import com.fasterxml.uuid.impl.TimeBasedGenerator; 6 | import org.protege.editor.owl.client.diff.model.*; 7 | import org.protege.owl.server.api.UserId; 8 | import org.semanticweb.owlapi.model.OWLObject; 9 | import org.semanticweb.owlapi.model.OWLOntologyChange; 10 | 11 | import java.util.Date; 12 | import java.util.Optional; 13 | import java.util.Set; 14 | 15 | /** 16 | * @author Rafael Gonçalves
17 | * Stanford Center for Biomedical Informatics Research 18 | */ 19 | public class DiffFactoryImpl implements DiffFactory { 20 | private final TimeBasedGenerator gen = Generators.timeBasedGenerator(EthernetAddress.fromInterface()); 21 | 22 | /** 23 | * No-args constructor 24 | */ 25 | public DiffFactoryImpl() { } 26 | 27 | @Override 28 | public Change createChange(ChangeId changeId, Set changes, ChangeDetails details, CommitMetadata commitMetadata, ChangeMode changeMode) { 29 | return new ChangeImpl(changeId, changes, details, commitMetadata, changeMode); 30 | } 31 | 32 | @Override 33 | public Change createChange(Set changes, ChangeDetails details, CommitMetadata commitMetadata, ChangeMode changeMode) { 34 | return createChange(createChangeId(), changes, details, commitMetadata, changeMode); 35 | } 36 | 37 | @Override 38 | public CommitId createCommitId(String commitId) { 39 | return new CommitIdImpl(commitId); 40 | } 41 | 42 | @Override 43 | public CommitMetadata createCommitMetadata(CommitId commitId, UserId userId, Date date, String comment) { 44 | return new CommitMetadataImpl(commitId, userId, date, comment); 45 | } 46 | 47 | @Override 48 | public ChangeDetails createChangeDetails(RevisionTag revisionTag, OWLObject changeSubject, ChangeType changeType, 49 | Optional property, Optional newValue) { 50 | return new ChangeDetailsImpl(revisionTag, changeSubject, changeType, property, newValue); 51 | } 52 | 53 | @Override 54 | public RevisionTag createRevisionTag(String revisionTag) { 55 | return new RevisionTagImpl(revisionTag); 56 | } 57 | 58 | @Override 59 | public ChangeId createChangeId() { 60 | return createChangeId(gen.generate().toString()); 61 | } 62 | 63 | @Override 64 | public ChangeId createChangeId(String changeId) { 65 | return new ChangeIdImpl(changeId); 66 | } 67 | 68 | @Override 69 | public Review createReview(ReviewStatus status, Optional author, Optional date, Optional comment, boolean isCommitted) { 70 | return new ReviewImpl(status, author, date, comment, isCommitted); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ConflictingCommitPanel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.OWLEditorKit; 4 | import org.protege.owl.server.api.UserId; 5 | import org.semanticweb.owlapi.model.OWLOntologyChange; 6 | 7 | import javax.swing.*; 8 | import javax.swing.border.EmptyBorder; 9 | import java.awt.*; 10 | import java.util.Date; 11 | import java.util.Set; 12 | 13 | import static com.google.common.base.Preconditions.checkNotNull; 14 | 15 | /** 16 | * @author Rafael Gonçalves
17 | * Stanford Center for Biomedical Informatics Research 18 | */ 19 | public class ConflictingCommitPanel extends JPanel { 20 | private final Set changes; 21 | private final Date commitDate; 22 | private final UserId commitAuthor; 23 | private final String commitComment; 24 | private final int conflictNr; 25 | private OWLEditorKit editorKit; 26 | private JList changeList = new JList<>(); 27 | 28 | /** 29 | * Constructor 30 | * 31 | * @param editorKit OWL editor kit 32 | * @param changes Set of ontology changes 33 | * @param commitDate Commit date 34 | * @param commitAuthor Commit author 35 | * @param commitComment Commit comment 36 | */ 37 | public ConflictingCommitPanel(OWLEditorKit editorKit, Set changes, Date commitDate, UserId commitAuthor, String commitComment, int conflictNr) { 38 | this.editorKit = checkNotNull(editorKit); 39 | this.changes = checkNotNull(changes); 40 | this.commitDate = checkNotNull(commitDate); 41 | this.commitAuthor = checkNotNull(commitAuthor); 42 | this.commitComment = checkNotNull(commitComment); 43 | this.conflictNr = checkNotNull(conflictNr); 44 | configureList(); 45 | setLayout(new BorderLayout()); 46 | setBackground(GuiUtils.WHITE_BACKGROUND); 47 | addConflictDetails(); 48 | } 49 | 50 | private void configureList() { 51 | changeList.setCellRenderer(new ChangeListCellRenderer(editorKit)); 52 | changeList.setSelectionModel(new DisabledListItemSelectionModel()); 53 | changeList.setFixedCellHeight(18); 54 | changeList.setFocusable(false); 55 | } 56 | 57 | private void addConflictDetails() { 58 | int fontSize = getFont().getSize(); 59 | String dateStr = GuiUtils.getShortenedFormattedDate(commitDate); 60 | String headerText = "Conflicting commit " + conflictNr + " by " + commitAuthor.getUserName() + " on " + dateStr + "
" + 61 | "

" + commitComment + "

"; 62 | 63 | JLabel headerLbl = new JLabel(headerText, GuiUtils.getIcon(GuiUtils.WARNING_ICON_FILENAME, 33, 33), SwingConstants.LEFT); 64 | headerLbl.setBorder(new EmptyBorder(0, 0, 8, 0)); 65 | headerLbl.setIconTextGap(8); 66 | add(headerLbl, BorderLayout.NORTH); 67 | 68 | changeList.setListData(changes.toArray(new OWLOntologyChange[changes.size()])); 69 | add(changeList, BorderLayout.CENTER); 70 | } 71 | } -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/action/EnableAutoUpdateAction.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.action; 2 | 3 | import org.protege.editor.core.ui.error.ErrorLogPanel; 4 | import org.protege.editor.owl.client.connect.ServerConnectionManager; 5 | import org.protege.editor.owl.ui.action.ProtegeOWLAction; 6 | import org.protege.owl.server.api.client.Client; 7 | import org.protege.owl.server.api.client.VersionedOntologyDocument; 8 | import org.protege.owl.server.api.exception.UserDeclinedAuthenticationException; 9 | import org.protege.owl.server.util.ClientUtilities; 10 | import org.semanticweb.owlapi.model.OWLOntology; 11 | 12 | import javax.swing.*; 13 | import java.awt.event.ActionEvent; 14 | import java.util.concurrent.ScheduledExecutorService; 15 | import java.util.concurrent.ScheduledFuture; 16 | import java.util.concurrent.TimeUnit; 17 | 18 | public class EnableAutoUpdateAction extends ProtegeOWLAction { 19 | private static final long serialVersionUID = 1098490684799516207L; 20 | private ScheduledFuture autoUpdate; 21 | private JCheckBoxMenuItem checkBoxMenuItem; 22 | private ServerConnectionManager connectionManager; 23 | 24 | public EnableAutoUpdateAction() { 25 | } 26 | 27 | @Override 28 | public void initialise() throws Exception { 29 | connectionManager = ServerConnectionManager.get(getOWLEditorKit()); 30 | } 31 | 32 | @Override 33 | public void dispose() throws Exception { 34 | 35 | } 36 | 37 | public void setMenuItem(JMenuItem menu) { 38 | checkBoxMenuItem = (JCheckBoxMenuItem) menu; 39 | } 40 | 41 | @Override 42 | public void actionPerformed(ActionEvent e) { 43 | if (autoUpdate != null) { 44 | autoUpdate.cancel(false); 45 | autoUpdate = null; 46 | } 47 | else { 48 | ScheduledExecutorService executor = connectionManager.getSingleThreadExecutorService(); 49 | autoUpdate = executor.scheduleWithFixedDelay(new AutoUpdate(), 15, 15, TimeUnit.SECONDS); // TODO: change this so that the sync delay value is fetched from the (new APIs) client configuration 50 | } 51 | } 52 | 53 | private class AutoUpdate implements Runnable { 54 | private boolean lastRunSuccessful = true; 55 | 56 | @Override 57 | public void run() { 58 | try { 59 | for (OWLOntology ontology : getOWLModelManager().getActiveOntologies()) { 60 | VersionedOntologyDocument vont = connectionManager.getVersionedOntology(ontology); 61 | if (vont != null) { 62 | Client client = connectionManager.createClient(vont.getServerDocument().getServerLocation()); 63 | ClientUtilities.update(client, vont); 64 | } 65 | } 66 | lastRunSuccessful = true; 67 | } 68 | catch (UserDeclinedAuthenticationException udae) { 69 | autoUpdate.cancel(false); 70 | autoUpdate = null; 71 | checkBoxMenuItem.setSelected(false); 72 | } 73 | catch (Throwable t) { 74 | if (!lastRunSuccessful) { 75 | ErrorLogPanel.showErrorDialog(t); 76 | } 77 | lastRunSuccessful = false; 78 | } 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangeListCellRenderer.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.OWLEditorKit; 4 | import org.protege.editor.owl.client.diff.model.LogDiff; 5 | import org.semanticweb.owlapi.model.*; 6 | 7 | import javax.swing.*; 8 | import java.awt.*; 9 | import java.io.Serializable; 10 | 11 | import static com.google.common.base.Preconditions.checkNotNull; 12 | 13 | /** 14 | * @author Rafael Gonçalves
15 | * Stanford Center for Biomedical Informatics Research 16 | */ 17 | public class ChangeListCellRenderer extends JTextArea implements ListCellRenderer, Serializable { 18 | private OwlCellRenderer owlCellRenderer; 19 | 20 | public ChangeListCellRenderer(OWLEditorKit editorKit) { 21 | super(); 22 | owlCellRenderer = new OwlCellRenderer(checkNotNull(editorKit)); 23 | } 24 | 25 | @Override 26 | public Component getListCellRendererComponent(JList list, OWLOntologyChange change, int index, boolean isSelected, boolean cellHasFocus) { 27 | if(change.isAxiomChange()) { 28 | OWLAxiom axiom = change.getAxiom(); 29 | Component c = owlCellRenderer.getListCellRendererComponent(list, axiom, index, isSelected, cellHasFocus); 30 | setBackground(list, change, c, isSelected); 31 | return c; 32 | } 33 | else if(change.isImportChange()) { 34 | OWLImportsDeclaration decl = ((ImportChange)change).getImportDeclaration(); 35 | Component c = owlCellRenderer.getListCellRendererComponent(list, decl.getIRI(), index, isSelected, cellHasFocus); 36 | setBackground(list, change, c, isSelected); 37 | return c; 38 | } 39 | else if(change instanceof SetOntologyID) { 40 | setText("New IRI: " + ((SetOntologyID)change).getNewOntologyID().getOntologyIRI().toString()); 41 | setBackground(list, change, this, isSelected); 42 | } 43 | else if(change instanceof AnnotationChange) { 44 | OWLAxiom axiom = getAnnotationAssertionAxiom((AnnotationChange)change); 45 | Component c = owlCellRenderer.getListCellRendererComponent(list, axiom, index, isSelected, cellHasFocus); 46 | setBackground(list, change, c, isSelected); 47 | return c; 48 | } 49 | return this; 50 | } 51 | 52 | private void setBackground(JList list, OWLOntologyChange change, Component c, boolean isSelected) { 53 | if (isSelected) { 54 | c.setBackground(list.getSelectionBackground()); 55 | c.setForeground(list.getSelectionForeground()); 56 | } 57 | else { 58 | GuiUtils.setComponentBackground(c, LogDiff.getChangeMode(change)); 59 | c.setForeground(GuiUtils.UNSELECTED_FOREGROUND); 60 | } 61 | } 62 | 63 | private OWLAnnotationAssertionAxiom getAnnotationAssertionAxiom(AnnotationChange change) { 64 | OWLAnnotation ann = change.getAnnotation(); 65 | OWLOntology ont = change.getOntology(); 66 | OWLDataFactory df = ont.getOWLOntologyManager().getOWLDataFactory(); 67 | return df.getOWLAnnotationAssertionAxiom(ont.getOntologyID().getOntologyIRI().get(), ann); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/action/ClientStatusTableModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.action; 2 | 3 | import java.util.List; 4 | 5 | import javax.swing.table.AbstractTableModel; 6 | 7 | import org.protege.editor.owl.client.panel.ChangeListTableModel.Column; 8 | import org.protege.owl.server.api.RevisionPointer; 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.ClientUtilities; 13 | import org.semanticweb.owlapi.model.OWLOntologyChange; 14 | 15 | public class ClientStatusTableModel extends AbstractTableModel { 16 | private static final long serialVersionUID = -465483270258124763L; 17 | 18 | public enum Column { 19 | NAME, VALUE; 20 | } 21 | 22 | public enum Row { 23 | SERVER_DOCUMENT("Server document:") { 24 | @Override 25 | public String evaluate(Client client, VersionedOntologyDocument vont) { 26 | return vont.getServerDocument().getServerLocation().toString(); 27 | } 28 | }, 29 | CLIENT_REVISION("Local revision:") { 30 | @Override 31 | public String evaluate(Client client, VersionedOntologyDocument vont) { 32 | return vont.getRevision().toString(); 33 | } 34 | }, 35 | SERVER_REVISION("Latest server revision:") { 36 | @Override 37 | public String evaluate(Client client, VersionedOntologyDocument vont) throws OWLServerException { 38 | return client.evaluateRevisionPointer(vont.getServerDocument(), RevisionPointer.HEAD_REVISION).toString(); 39 | } 40 | }, 41 | UNCOMMITTED_CHANGES("# of uncommitted changes:") { 42 | @Override 43 | public String evaluate(Client client, VersionedOntologyDocument vont) throws OWLServerException { 44 | List changes = ClientUtilities.getUncommittedChanges(client, vont); 45 | return "" + changes.size(); 46 | } 47 | } 48 | ; 49 | 50 | private String name; 51 | 52 | private Row(String name) { 53 | this.name = name; 54 | } 55 | 56 | public String getName() { 57 | return name; 58 | } 59 | public abstract Object evaluate(Client client, VersionedOntologyDocument vont) throws OWLServerException; 60 | } 61 | 62 | private Client client; 63 | private VersionedOntologyDocument vont; 64 | 65 | public ClientStatusTableModel(Client client, VersionedOntologyDocument vont) { 66 | this.client = client; 67 | this.vont = vont; 68 | } 69 | 70 | @Override 71 | public int getRowCount() { 72 | return Row.values().length; 73 | } 74 | 75 | @Override 76 | public int getColumnCount() { 77 | return Column.values().length; 78 | } 79 | 80 | @Override 81 | public Object getValueAt(int rowIndex, int columnIndex) { 82 | if (vont == null) { 83 | return "Not a server ontology"; 84 | } 85 | Row row = Row.values()[rowIndex]; 86 | Column column = Column.values()[columnIndex]; 87 | try { 88 | switch (column) { 89 | case NAME: 90 | return row.getName(); 91 | case VALUE: 92 | return row.evaluate(client, vont); 93 | default: 94 | return "Unknown column type"; 95 | } 96 | } 97 | catch (OWLServerException e) { 98 | return "Error: " + e.getMessage(); 99 | } 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ChangeDetailsImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | import org.semanticweb.owlapi.model.OWLObject; 6 | 7 | import java.util.Optional; 8 | 9 | import static com.google.common.base.Preconditions.checkNotNull; 10 | 11 | /** 12 | * @author Rafael Gonçalves
13 | * Stanford Center for Biomedical Informatics Research 14 | */ 15 | public final class ChangeDetailsImpl implements ChangeDetails { 16 | private final RevisionTag revisionTag; 17 | private final OWLObject changeSubject, property; 18 | private final ChangeType changeType; 19 | private final String newValue; 20 | 21 | /** 22 | * Constructor 23 | * 24 | * @param revisionTag Revision tag 25 | * @param changeSubject OWL entity that is the change subject 26 | * @param changeType Change type 27 | * @param property Annotation property whose value has changed 28 | * @param newValue New value of the annotation property 29 | */ 30 | public ChangeDetailsImpl(RevisionTag revisionTag, OWLObject changeSubject, ChangeType changeType, Optional property, Optional newValue) { 31 | this.revisionTag = checkNotNull(revisionTag); 32 | this.changeSubject = checkNotNull(changeSubject); 33 | this.changeType = checkNotNull(changeType); 34 | this.property = (property.isPresent() ? checkNotNull(property.get()) : null); 35 | this.newValue = (newValue.isPresent() ? checkNotNull(newValue.get()) : null); 36 | } 37 | 38 | @Override 39 | public RevisionTag getRevisionTag() { 40 | return revisionTag; 41 | } 42 | 43 | @Override 44 | public OWLObject getSubject() { 45 | return changeSubject; 46 | } 47 | 48 | @Override 49 | public ChangeType getType() { 50 | return changeType; 51 | } 52 | 53 | @Override 54 | public Optional getProperty() { 55 | return Optional.ofNullable(property); 56 | } 57 | 58 | @Override 59 | public Optional getNewValue() { 60 | return Optional.ofNullable(newValue); 61 | } 62 | 63 | @Override 64 | public boolean equals(Object o) { 65 | if (this == o) return true; 66 | if (o == null || getClass() != o.getClass()) return false; 67 | ChangeDetailsImpl that = (ChangeDetailsImpl) o; 68 | return Objects.equal(revisionTag, that.revisionTag) && 69 | Objects.equal(changeSubject, that.changeSubject) && 70 | Objects.equal(property, that.property) && 71 | Objects.equal(changeType, that.changeType) && 72 | Objects.equal(newValue, that.newValue); 73 | } 74 | 75 | @Override 76 | public int hashCode() { 77 | return Objects.hashCode(revisionTag, changeSubject, property, changeType, newValue); 78 | } 79 | 80 | @Override 81 | public String toString() { 82 | return MoreObjects.toStringHelper(this) 83 | .add("revisionTag", revisionTag) 84 | .add("changeSubject", changeSubject) 85 | .add("property", property) 86 | .add("changeType", changeType) 87 | .add("newValue", newValue) 88 | .toString(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/CommitPanel.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.CommitMetadata; 6 | import org.protege.editor.owl.client.diff.model.LogDiffEvent; 7 | import org.protege.editor.owl.client.diff.model.LogDiffListener; 8 | import org.protege.editor.owl.client.diff.model.LogDiffManager; 9 | import org.protege.editor.owl.model.OWLModelManager; 10 | 11 | import javax.swing.*; 12 | import javax.swing.event.ListSelectionListener; 13 | import java.awt.*; 14 | import java.util.List; 15 | 16 | /** 17 | * @author Rafael Gonçalves
18 | * Stanford Center for Biomedical Informatics Research 19 | */ 20 | public class CommitPanel extends JPanel implements Disposable { 21 | private static final long serialVersionUID = 982230736000168376L; 22 | private LogDiffManager diffManager; 23 | private JList commitList = new JList<>(); 24 | 25 | /** 26 | * Constructor 27 | * 28 | * @param modelManager OWL model manager 29 | * @param editorKit OWL editor kit 30 | */ 31 | public CommitPanel(OWLModelManager modelManager, OWLEditorKit editorKit) { 32 | diffManager = LogDiffManager.get(modelManager, editorKit); 33 | diffManager.addListener(diffListener); 34 | setLayout(new BorderLayout(20, 20)); 35 | setupList(); 36 | 37 | JScrollPane scrollPane = new JScrollPane(commitList); 38 | scrollPane.setBorder(GuiUtils.EMPTY_BORDER); 39 | scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 40 | add(scrollPane, BorderLayout.CENTER); 41 | listCommits(LogDiffEvent.ONTOLOGY_UPDATED); 42 | } 43 | 44 | private ListSelectionListener listSelectionListener = e -> { 45 | CommitMetadata selection = commitList.getSelectedValue(); 46 | if (selection != null && !e.getValueIsAdjusting()) { 47 | diffManager.setSelectedCommit(selection); 48 | } 49 | }; 50 | 51 | private LogDiffListener diffListener = event -> { 52 | if (event.equals(LogDiffEvent.AUTHOR_SELECTION_CHANGED) || event.equals(LogDiffEvent.ONTOLOGY_UPDATED)) { 53 | diffManager.clearSelectedChanges(); 54 | listCommits(event); 55 | } 56 | }; 57 | 58 | private void setupList() { 59 | commitList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 60 | commitList.addListSelectionListener(listSelectionListener); 61 | commitList.setCellRenderer(new CommitListCellRenderer()); 62 | commitList.setFixedCellHeight(45); 63 | commitList.setFixedCellWidth(this.getWidth()); 64 | commitList.setBorder(GuiUtils.MATTE_BORDER); 65 | } 66 | 67 | private void listCommits(LogDiffEvent event) { 68 | if(diffManager.getVersionedOntologyDocument().isPresent()) { 69 | List commits = diffManager.getCommits(event); 70 | commitList.setListData(commits.toArray(new CommitMetadata[commits.size()])); 71 | } 72 | else { 73 | commitList.setListData(new CommitMetadata[0]); 74 | } 75 | } 76 | 77 | @Override 78 | public void dispose() { 79 | commitList.removeListSelectionListener(listSelectionListener); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/panel/ServerTableModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.panel; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.Comparator; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | 9 | import javax.swing.table.AbstractTableModel; 10 | 11 | import org.protege.owl.server.api.client.Client; 12 | import org.protege.owl.server.api.client.RemoteServerDirectory; 13 | import org.protege.owl.server.api.client.RemoteServerDocument; 14 | import org.protege.owl.server.api.exception.OWLServerException; 15 | 16 | 17 | public class ServerTableModel extends AbstractTableModel { 18 | private static final long serialVersionUID = -1677982790864801841L; 19 | 20 | /* 21 | * some growth coming... 22 | */ 23 | public enum Column { 24 | SERVER_DOCUMENT_LOCATION; 25 | } 26 | private List serverDocuments = new ArrayList(); 27 | 28 | public void loadServerData(Client client, RemoteServerDirectory dir) throws OWLServerException { 29 | List docs = new ArrayList(client.list(dir)); 30 | 31 | /* 32 | * Tim and Jenn decided that for the first release, there shouldn't be any server directories 33 | * exposed to the user - only a list of ontology documents. Server folder structure will come later. 34 | */ 35 | Iterator iterator = docs.iterator(); 36 | while (iterator.hasNext()) { 37 | RemoteServerDocument doc = iterator.next(); 38 | if (doc instanceof RemoteServerDirectory) { 39 | iterator.remove(); 40 | } 41 | } 42 | 43 | Collections.sort(docs, new Comparator() { 44 | @Override 45 | public int compare(RemoteServerDocument doc1, RemoteServerDocument doc2) { 46 | return doc1.getServerLocation().compareTo(doc2.getServerLocation()); 47 | } 48 | }); 49 | serverDocuments = docs; 50 | fireTableStructureChanged(); 51 | } 52 | 53 | @Override 54 | public int getColumnCount() { 55 | return Column.values().length; 56 | } 57 | 58 | @Override 59 | public String getColumnName(int col) { 60 | Column column = Column.values()[col]; 61 | switch (column) { 62 | case SERVER_DOCUMENT_LOCATION: 63 | return "Ontology Documents"; 64 | default: 65 | throw new IllegalStateException("Programmer missed a case"); 66 | } 67 | } 68 | 69 | @Override 70 | public int getRowCount() { 71 | return serverDocuments.size(); 72 | } 73 | 74 | @Override 75 | public Object getValueAt(int row, int col) { 76 | Column column = Column.values()[col]; 77 | RemoteServerDocument doc = serverDocuments.get(row); 78 | switch (column) { 79 | case SERVER_DOCUMENT_LOCATION: 80 | String fragment = doc.getServerLocation().getFragment(); 81 | if (fragment == null || fragment.isEmpty()) { 82 | String path = doc.getServerLocation().toURI().getPath(); 83 | if (path.endsWith("/")) { 84 | path = path.substring(0, path.length() - 1); 85 | } 86 | int start = path.lastIndexOf('/'); 87 | return path.substring(start + 1); 88 | } 89 | else return fragment; 90 | default: 91 | throw new IllegalStateException("Programmer missed a case"); 92 | } 93 | } 94 | 95 | public RemoteServerDocument getValueAt(int row) { 96 | return serverDocuments.get(row); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/GuiUtils.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.client.diff.model.ChangeMode; 4 | 5 | import javax.imageio.ImageIO; 6 | import javax.swing.*; 7 | import javax.swing.border.Border; 8 | import javax.swing.border.EmptyBorder; 9 | import javax.swing.border.MatteBorder; 10 | import java.awt.*; 11 | import java.awt.image.BufferedImage; 12 | import java.io.IOException; 13 | import java.text.SimpleDateFormat; 14 | import java.util.Date; 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 GuiUtils { 23 | 24 | /* constants */ 25 | 26 | public static final Color 27 | ADDITION_COLOR = new Color(219, 253, 217), 28 | REMOVAL_COLOR = new Color(255, 221, 220), 29 | ONTOLOGY_IRI_COLOR = new Color(242, 248, 255), 30 | DEFAULT_CHANGE_COLOR = new Color(250, 242, 209), 31 | WHITE_BACKGROUND = Color.WHITE, 32 | UNSELECTED_FOREGROUND = Color.BLACK, 33 | BORDER_COLOR = new Color(220, 220, 220); 34 | 35 | public static final Border 36 | MATTE_BORDER = new MatteBorder(1, 1, 1, 1, BORDER_COLOR), 37 | EMPTY_BORDER = new EmptyBorder(0,0,0,0); 38 | 39 | public static final String 40 | USER_ICON_FILENAME = "user.png", 41 | USERS_ICON_FILENAME = "users.png", 42 | COMMIT_ICON_FILENAME = "commit.png", 43 | STRING_ICON_FILENAME = "string.png", 44 | ONTOLOGY_ICON_FILENAME = "ontology.png", 45 | WARNING_ICON_FILENAME = "warning.png", 46 | REVIEW_ACCEPTED_ICON_FILENAME = "review-accepted.png", 47 | REVIEW_REJECTED_ICON_FILENAME = "review-rejected.png", 48 | REVIEW_CLEAR_ICON_FILENAME = "review-clear.png", 49 | REVIEW_COMMIT_ICON_FILENAME = "review-commit.png", 50 | REVIEW_PENDING_ICON_FILENAME = "review-pending.png", 51 | NEW_REVIEW_ICON_FILENAME = "review-new.png"; 52 | 53 | 54 | /* methods */ 55 | 56 | public static Icon getIcon(String filename, int width, int height) { 57 | BufferedImage icon = null; 58 | ClassLoader classLoader = GuiUtils.class.getClassLoader(); 59 | try { 60 | icon = ImageIO.read(checkNotNull(classLoader.getResource(filename))); 61 | } catch (IOException e) { 62 | e.printStackTrace(); 63 | } 64 | Image img = icon.getScaledInstance(width, height, Image.SCALE_SMOOTH); 65 | return new ImageIcon(img); 66 | } 67 | 68 | public static void setComponentBackground(Component c, ChangeMode mode) { 69 | switch(mode) { 70 | case ADDITION: 71 | c.setBackground(ADDITION_COLOR); break; 72 | case REMOVAL: 73 | c.setBackground(REMOVAL_COLOR); break; 74 | case ONTOLOGY_IRI: 75 | c.setBackground(ONTOLOGY_IRI_COLOR); break; 76 | case ALIGNED: 77 | case CUSTOM: 78 | default: 79 | c.setBackground(DEFAULT_CHANGE_COLOR); break; 80 | } 81 | } 82 | 83 | public static String getFormattedDate(Date date) { 84 | return new SimpleDateFormat("EEE, MMM d yyyy HH:mm").format(date); 85 | } 86 | 87 | public static String getShortenedFormattedDate(Date date) { 88 | return new SimpleDateFormat("MMM d yyyy HH:mm").format(date); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/OwlObjectList.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.core.ui.list.MList; 4 | import org.protege.editor.core.ui.list.MListItem; 5 | import org.protege.editor.owl.OWLEditorKit; 6 | 7 | import javax.swing.*; 8 | import java.awt.*; 9 | import java.util.Set; 10 | import java.util.Vector; 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 OwlObjectList extends MList { 19 | private static final long serialVersionUID = -6582688251102782964L; 20 | 21 | /** 22 | * Constructor 23 | * 24 | * @param editorKit OWL editor kit 25 | */ 26 | public OwlObjectList(OWLEditorKit editorKit) { 27 | setCellRenderer(new ListItemRenderer(editorKit, true, true)); 28 | setFixedCellHeight(30); 29 | setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 30 | setSelectionModel(new DisabledItemSelectionModel()); 31 | } 32 | 33 | public void setObjects(Set objects) { 34 | Vector> items = new Vector<>(); 35 | for(E e : objects) { 36 | items.add(new ListItem<>(e)); 37 | } 38 | setListData(items); 39 | } 40 | 41 | public void setObject(E object) { 42 | Vector> items = new Vector<>(); 43 | items.add(new ListItem<>(object)); 44 | setListData(items); 45 | } 46 | 47 | 48 | private class ListItemRenderer implements ListCellRenderer> { 49 | private OwlCellRenderer renderer; 50 | 51 | public ListItemRenderer(OWLEditorKit owlEditorKit, boolean renderExpression, boolean renderIcon) { 52 | renderer = new OwlCellRenderer(owlEditorKit, renderExpression, renderIcon); 53 | } 54 | 55 | @Override 56 | public Component getListCellRendererComponent(JList> list, ListItem value, int index, boolean isSelected, boolean cellHasFocus) { 57 | return renderer.getListCellRendererComponent(list, value.getObject(), index, isSelected, cellHasFocus); 58 | } 59 | } 60 | 61 | 62 | private class ListItem implements MListItem { 63 | private E object; 64 | 65 | public ListItem(E object) { 66 | this.object = checkNotNull(object); 67 | } 68 | 69 | public boolean isEditable() { 70 | return false; 71 | } 72 | 73 | public void handleEdit() { 74 | // do nothing 75 | } 76 | 77 | public boolean isDeleteable() { 78 | return false; 79 | } 80 | 81 | public boolean handleDelete() { 82 | return false; 83 | } 84 | 85 | public String getTooltip() { 86 | return ""; 87 | } 88 | 89 | public E getObject() { 90 | return object; 91 | } 92 | } 93 | 94 | 95 | private class DisabledItemSelectionModel extends DefaultListSelectionModel { 96 | @Override 97 | public void setSelectionInterval(int index0, int index1) { 98 | super.setSelectionInterval(-1, -1); 99 | } 100 | 101 | @Override 102 | public void addSelectionInterval(int index0, int index1) { 103 | super.addSelectionInterval(-1, -1); 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ReviewImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | import org.protege.owl.server.api.UserId; 6 | 7 | import java.util.Date; 8 | import java.util.Optional; 9 | 10 | import static com.google.common.base.Preconditions.checkNotNull; 11 | 12 | /** 13 | * @author Rafael Gonçalves
14 | * Stanford Center for Biomedical Informatics Research 15 | */ 16 | public class ReviewImpl implements Review { 17 | private ReviewStatus status; 18 | private UserId author; 19 | private Date date; 20 | private String comment; 21 | private boolean isCommitted; 22 | 23 | /** 24 | * Constructor 25 | * 26 | * @param status Change review status 27 | * @param author Review author 28 | * @param date Review date 29 | * @param comment Review comment 30 | */ 31 | public ReviewImpl(ReviewStatus status, Optional author, Optional date, Optional comment, boolean isCommitted) { 32 | this.status = checkNotNull(status); 33 | this.author = (author.isPresent() ? checkNotNull(author.get()) : null); 34 | this.date = (date.isPresent() ? checkNotNull(date.get()) : null); 35 | this.comment = (comment.isPresent() ? checkNotNull(comment.get()) : null); 36 | this.isCommitted = checkNotNull(isCommitted); 37 | } 38 | 39 | @Override 40 | public Optional getAuthor() { 41 | return Optional.ofNullable(author); 42 | } 43 | 44 | @Override 45 | public Optional getDate() { 46 | return Optional.ofNullable(date); 47 | } 48 | 49 | @Override 50 | public ReviewStatus getStatus() { 51 | return status; 52 | } 53 | 54 | @Override 55 | public Optional getComment() { 56 | return Optional.ofNullable(comment); 57 | } 58 | 59 | @Override 60 | public boolean isCommitted() { 61 | return isCommitted; 62 | } 63 | 64 | @Override 65 | public void setAuthor(UserId author) { 66 | this.author = checkNotNull(author); 67 | } 68 | 69 | @Override 70 | public void setDate(Date date) { 71 | this.date = checkNotNull(date); 72 | } 73 | 74 | @Override 75 | public void setStatus(ReviewStatus status) { 76 | this.status = checkNotNull(status); 77 | } 78 | 79 | @Override 80 | public void setComment(String comment) { 81 | this.comment = checkNotNull(comment); 82 | } 83 | 84 | @Override 85 | public void setCommitted(boolean committed) { 86 | isCommitted = checkNotNull(committed); 87 | } 88 | 89 | @Override 90 | public boolean equals(Object o) { 91 | if (this == o) return true; 92 | if (o == null || getClass() != o.getClass()) return false; 93 | ReviewImpl that = (ReviewImpl) o; 94 | return Objects.equal(author, that.author) && 95 | Objects.equal(date, that.date) && 96 | Objects.equal(status, that.status) && 97 | Objects.equal(comment, that.comment); 98 | } 99 | 100 | @Override 101 | public int hashCode() { 102 | return Objects.hashCode(author, date, status, comment); 103 | } 104 | 105 | @Override 106 | public String toString() { 107 | return MoreObjects.toStringHelper(this) 108 | .add("author", author) 109 | .add("date", date) 110 | .add("status", status) 111 | .add("comment", comment) 112 | .toString(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangeDetailsTableCellRenderer.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.OWLEditorKit; 4 | import org.protege.editor.owl.client.diff.model.ChangeMode; 5 | import org.protege.editor.owl.client.diff.model.LogDiff; 6 | import org.protege.editor.owl.model.OWLModelManager; 7 | import org.semanticweb.owlapi.model.*; 8 | 9 | import javax.swing.*; 10 | import java.awt.*; 11 | 12 | /** 13 | * @author Rafael Gonçalves
14 | * Stanford Center for Biomedical Informatics Research 15 | */ 16 | public class ChangeDetailsTableCellRenderer extends LogDiffCellRenderer { 17 | private OWLModelManager modelManager; 18 | 19 | /** 20 | * Constructor 21 | * 22 | * @param editorKit OWL editor kit 23 | */ 24 | public ChangeDetailsTableCellRenderer(OWLEditorKit editorKit) { 25 | super(editorKit); 26 | this.modelManager = editorKit.getOWLModelManager(); 27 | } 28 | 29 | @Override 30 | public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 31 | ChangeMode mode = LogDiff.getChangeMode((OWLOntologyChange)value); 32 | if (value instanceof OWLAxiomChange) { 33 | OWLAxiom ax = ((OWLAxiomChange)value).getAxiom(); 34 | JComponent c = (JComponent) owlCellRenderer.getTableCellRendererComponent(table, ax, isSelected, hasFocus, row, column); 35 | setBackground(table, mode, c, isSelected); 36 | c.setToolTipText(modelManager.getRendering(ax)); 37 | return c; 38 | } 39 | else if(value instanceof AnnotationChange) { 40 | OWLAxiom ax = getAnnotationAssertionAxiom((AnnotationChange) value); 41 | JComponent c = (JComponent) owlCellRenderer.getTableCellRendererComponent(table, ax, isSelected, hasFocus, row, column); 42 | setBackground(table, mode, c, isSelected); 43 | c.setToolTipText(modelManager.getRendering(ax)); 44 | return c; 45 | } 46 | else if(value instanceof ImportChange) { 47 | OWLImportsDeclaration decl = ((ImportChange)value).getImportDeclaration(); 48 | JComponent c = (JComponent) owlCellRenderer.getTableCellRendererComponent(table, decl.getIRI(), isSelected, hasFocus, row, column); 49 | setBackground(table, mode, c, isSelected); 50 | c.setToolTipText(modelManager.getRendering(decl.getIRI())); 51 | return c; 52 | } 53 | else if(value instanceof SetOntologyID) { 54 | IRI newIri = ((SetOntologyID)value).getNewOntologyID().getOntologyIRI().get(); 55 | setText("New IRI: " + newIri); 56 | setToolTipText(modelManager.getRendering(newIri)); 57 | } 58 | setBackground(table, mode, this, isSelected); 59 | setFont(table.getFont()); 60 | return this; 61 | } 62 | 63 | private OWLAnnotationAssertionAxiom getAnnotationAssertionAxiom(AnnotationChange change) { 64 | OWLAnnotation ann = change.getAnnotation(); 65 | OWLOntology ont = change.getOntology(); 66 | OWLDataFactory df = ont.getOWLOntologyManager().getOWLDataFactory(); 67 | return df.getOWLAnnotationAssertionAxiom(ont.getOntologyID().getOntologyIRI().get(), ann); 68 | } 69 | 70 | private void setBackground(JTable table, ChangeMode mode, Component c, boolean isSelected) { 71 | if (isSelected) { 72 | c.setBackground(table.getSelectionBackground()); 73 | c.setForeground(table.getSelectionForeground()); 74 | } 75 | else { 76 | GuiUtils.setComponentBackground(c, mode); 77 | c.setForeground(GuiUtils.UNSELECTED_FOREGROUND); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/Change.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import org.semanticweb.owlapi.model.OWLOntologyChange; 4 | 5 | import java.util.Optional; 6 | import java.util.Set; 7 | 8 | /** 9 | * @author Rafael Gonçalves
10 | * Stanford Center for Biomedical Informatics Research 11 | */ 12 | public interface Change extends Comparable { 13 | 14 | /** 15 | * Get the change identifier 16 | * 17 | * @return Change identifier 18 | */ 19 | ChangeId getId(); 20 | 21 | /** 22 | * Get the set of ontology changes involved in this change 23 | * 24 | * @return Set of OWLOntologyChange 25 | */ 26 | Set getChanges(); 27 | 28 | /** 29 | * Get the change details object containing further information 30 | * about this change, such as its author, type, subject, ... 31 | * 32 | * @return Change details 33 | */ 34 | ChangeDetails getDetails(); 35 | 36 | /** 37 | * Get the commit metadata, such as author, date and comment 38 | * 39 | * @return Commit metadata 40 | */ 41 | CommitMetadata getCommitMetadata(); 42 | 43 | /** 44 | * Get the change mode, i.e., addition, removal or ontology IRI change 45 | * 46 | * @return Change mode 47 | */ 48 | ChangeMode getMode(); 49 | 50 | /** 51 | * Set the change mode 52 | * 53 | * @param mode Change mode 54 | */ 55 | void setMode(ChangeMode mode); 56 | 57 | /** 58 | * Check whether this change is of the specified type 59 | * 60 | * @param type Change type 61 | * @return true if this change is of the type specified, false otherwise 62 | */ 63 | boolean isOfType(ChangeType type); 64 | 65 | /** 66 | * Add a change that is in conflict with this one 67 | * 68 | * @param conflictingChange Conflicting change 69 | */ 70 | void addConflictingChange(ChangeId conflictingChange); 71 | 72 | /** 73 | * Get the set of changes that conflict with this one 74 | * 75 | * @return Set of conflicting changes 76 | */ 77 | Set getConflictingChanges(); 78 | 79 | /** 80 | * Check if change is in conflict with some other change(s) 81 | * 82 | * @return true if change conflicts with others, false otherwise 83 | */ 84 | boolean isConflicting(); 85 | 86 | /** 87 | * Get the review of this change, i.e., whether it's pending review, 88 | * is accepted, or is rejected, the review author, date and comment 89 | * 90 | * @return Review 91 | */ 92 | Review getReview(); 93 | 94 | /** 95 | * Set the review for this change 96 | * 97 | * @param review Review 98 | */ 99 | void setReview(Review review); 100 | 101 | /** 102 | * Convenience method to set the review status of the change's review 103 | * 104 | * @param status Review status 105 | */ 106 | void setReviewStatus(ReviewStatus status); 107 | 108 | /** 109 | * Get the review status of this change, i.e., whether review is pending, 110 | * the change was accepted or rejected 111 | * 112 | * @return Change review status 113 | */ 114 | ReviewStatus getReviewStatus(); 115 | 116 | /** 117 | * Get the baseline ontology change for this change, if one exists 118 | * 119 | * @return Baseline ontology change 120 | */ 121 | Optional getBaselineChange(); 122 | 123 | /** 124 | * Set the baseline ontology change for this change 125 | * 126 | * @param change OWL ontology change 127 | */ 128 | void setBaselineChange(OWLOntologyChange change); 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/SimpleConflictDetector.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import org.apache.log4j.Logger; 4 | import org.protege.owl.server.api.UserId; 5 | import org.semanticweb.owlapi.model.OWLAxiom; 6 | import org.semanticweb.owlapi.model.OWLOntologyChange; 7 | 8 | import java.util.Collection; 9 | import java.util.HashSet; 10 | import java.util.Set; 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 final class SimpleConflictDetector implements ConflictDetector { 19 | private static final Logger log = Logger.getLogger(SimpleConflictDetector.class); 20 | private static final Strategy DEFAULT_STRATEGY = Strategy.SAME_TYPE_AND_ANNOTATION_PROPERTY; 21 | 22 | /** 23 | * No-args constructor 24 | */ 25 | public SimpleConflictDetector() { } 26 | 27 | @Override 28 | public Set getConflictingChanges(Change seed, Collection searchSpace) { 29 | return getConflictingChanges(seed, DEFAULT_STRATEGY, searchSpace); 30 | } 31 | 32 | private Set getConflictingChanges(Change seed, Strategy strategy, Collection searchSpace) { 33 | checkNotNull(seed); 34 | checkNotNull(strategy); 35 | checkNotNull(searchSpace); 36 | UserId userId = seed.getCommitMetadata().getAuthor(); 37 | Set conflictingChanges = new HashSet<>(); 38 | // The search space is restricted to changes with the same change subject 39 | for (Change change : searchSpace) { 40 | if (!(change.getCommitMetadata().getAuthor().equals(userId))) { 41 | if (strategy.equals(Strategy.LOOSE) || (strategy.equals(Strategy.SAME_TYPE) && isSameType(seed, change))) { 42 | conflictingChanges.add(change.getId()); 43 | } else if (strategy.equals(Strategy.SAME_TYPE_AND_ANNOTATION_PROPERTY) && isSameType(seed, change)) { 44 | if (seed.getDetails().getType().equals(BuiltInChangeType.ANNOTATION) || 45 | seed.getDetails().getType().equals(BuiltInChangeType.ONTOLOGY_ANNOTATION)) { 46 | if (seed.getDetails().getProperty().isPresent() && change.getDetails().getProperty().isPresent()) { 47 | if (seed.getDetails().getProperty().get().equals(change.getDetails().getProperty().get())) { 48 | conflictingChanges.add(change.getId()); 49 | } 50 | } 51 | } else { 52 | conflictingChanges.add(change.getId()); 53 | } 54 | } 55 | } 56 | } 57 | return conflictingChanges; 58 | } 59 | 60 | private boolean isSameType(Change c1, Change c2) { 61 | return c1.getDetails().getType().equals(c2.getDetails().getType()) && axiomTypesMatch(c1, c2); 62 | } 63 | 64 | private boolean axiomTypesMatch(Change c1, Change c2) { 65 | if(c1.getChanges().size() == 1 && c2.getChanges().size() == 1) { 66 | OWLOntologyChange oc1 = c1.getChanges().iterator().next(); 67 | OWLOntologyChange oc2 = c2.getChanges().iterator().next(); 68 | if(oc1.isAxiomChange() && oc2.isAxiomChange()) { 69 | OWLAxiom ax1 = oc1.getAxiom(), ax2 = oc2.getAxiom(); 70 | return ax1.getAxiomType().equals(ax2.getAxiomType()); 71 | } 72 | } 73 | else { 74 | log.error("Cannot find conflicts for composite changes (i.e., changes that involve multiple OWL ontology changes)"); 75 | } 76 | return true; 77 | } 78 | 79 | public enum Strategy { 80 | LOOSE, SAME_TYPE, SAME_TYPE_AND_ANNOTATION_PROPERTY 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/action/ShowUncommittedChangesAction.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.action; 2 | 3 | import org.protege.editor.core.ui.error.ErrorLogPanel; 4 | import org.protege.editor.owl.client.connect.ServerConnectionManager; 5 | import org.protege.editor.owl.client.panel.ChangeListTableModel; 6 | import org.protege.editor.owl.ui.action.ProtegeOWLAction; 7 | import org.protege.editor.owl.ui.renderer.OWLCellRenderer; 8 | import org.protege.owl.server.api.client.Client; 9 | import org.protege.owl.server.api.client.VersionedOntologyDocument; 10 | import org.protege.owl.server.api.exception.UserDeclinedAuthenticationException; 11 | import org.protege.owl.server.util.ClientUtilities; 12 | import org.semanticweb.owlapi.model.OWLObject; 13 | import org.semanticweb.owlapi.model.OWLOntology; 14 | import org.semanticweb.owlapi.model.OWLOntologyChange; 15 | import org.semanticweb.owlapi.model.OWLOntologyID; 16 | 17 | import javax.swing.*; 18 | import java.awt.*; 19 | import java.awt.event.ActionEvent; 20 | import java.util.List; 21 | 22 | public class ShowUncommittedChangesAction extends ProtegeOWLAction { 23 | private static final long serialVersionUID = -7628375950917155764L; 24 | 25 | @Override 26 | public void initialise() throws Exception { 27 | 28 | } 29 | 30 | @Override 31 | public void dispose() throws Exception { 32 | 33 | } 34 | 35 | @Override 36 | public void actionPerformed(ActionEvent arg0) { 37 | try { 38 | ServerConnectionManager connectionManager = ServerConnectionManager.get(getOWLEditorKit()); 39 | OWLOntology ontology = getOWLModelManager().getActiveOntology(); 40 | 41 | VersionedOntologyDocument vont = connectionManager.getVersionedOntology(ontology); 42 | if (vont != null) { 43 | Client client = connectionManager.createClient(ontology); 44 | List uncommitted = ClientUtilities.getUncommittedChanges(client, vont); 45 | connectionManager.saveHistoryInBackground(vont); 46 | if (uncommitted.isEmpty()) { 47 | JOptionPane.showMessageDialog(getOWLWorkspace(), "No uncommitted changes"); 48 | } else { 49 | displayUncommittedChanges(ontology, uncommitted); 50 | } 51 | } 52 | else { 53 | JOptionPane.showMessageDialog(getOWLWorkspace(), "Active ontology is not connected to a server."); 54 | } 55 | } 56 | catch (UserDeclinedAuthenticationException udae) { 57 | ; // ignore this because the user knows that he didn't authenticate. 58 | } 59 | catch (Exception e) { 60 | ErrorLogPanel.showErrorDialog(e); 61 | } 62 | } 63 | 64 | private void displayUncommittedChanges(OWLOntology ontology, List uncommitted) { 65 | String shortOntologyName = ""; 66 | OWLOntologyID ontologyId = ontology.getOntologyID(); 67 | if (!ontologyId.isAnonymous()) { 68 | shortOntologyName = ontology.getOntologyID().getOntologyIRI().get().getRemainder().get(); 69 | } 70 | if (shortOntologyName.isEmpty()) { 71 | shortOntologyName = ontologyId.toString(); 72 | } 73 | ChangeListTableModel tableModel = new ChangeListTableModel(uncommitted); 74 | JTable table = new JTable(tableModel); 75 | table.setDefaultRenderer(OWLObject.class, new OWLCellRenderer(getOWLEditorKit())); 76 | JScrollPane pane = new JScrollPane(table); 77 | JDialog dialog = new JDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, getOWLWorkspace())); 78 | dialog.setTitle("Uncommitted changes for " + shortOntologyName); 79 | dialog.getContentPane().add(pane); 80 | dialog.setResizable(true); 81 | dialog.setModal(true); 82 | dialog.pack(); 83 | dialog.setVisible(true); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/DiffFactory.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff; 2 | 3 | import org.protege.editor.owl.client.diff.model.*; 4 | import org.protege.owl.server.api.UserId; 5 | import org.semanticweb.owlapi.model.OWLObject; 6 | import org.semanticweb.owlapi.model.OWLOntologyChange; 7 | 8 | import java.util.Date; 9 | import java.util.Optional; 10 | import java.util.Set; 11 | 12 | /** 13 | * @author Rafael Gonçalves
14 | * Stanford Center for Biomedical Informatics Research 15 | */ 16 | public interface DiffFactory { 17 | 18 | /** 19 | * Create an instance of a Change 20 | * 21 | * @param changeId Change unique identifier 22 | * @param changes Set of OWL ontology changes 23 | * @param details Change details 24 | * @param commitMetadata Commit metadata 25 | * @param changeMode Change mode 26 | * @return Change instance 27 | */ 28 | Change createChange(ChangeId changeId, Set changes, ChangeDetails details, CommitMetadata commitMetadata, ChangeMode changeMode); 29 | 30 | /** 31 | * Create an instance of a Change where the change identifier is an automatically generated UUID 32 | * 33 | * @param changes Set of OWL ontology changes 34 | * @param details Change details 35 | * @param commitMetadata Commit metadata 36 | * @param changeMode Change mode 37 | * @return Change instance 38 | */ 39 | Change createChange(Set changes, ChangeDetails details, CommitMetadata commitMetadata, ChangeMode changeMode); 40 | 41 | /** 42 | * Create a commit identifier 43 | * 44 | * @param commitId Commit identifier 45 | * @return Commit identifier string 46 | */ 47 | CommitId createCommitId(String commitId); 48 | 49 | /** 50 | * Create an instance of commit metadata 51 | * 52 | * @param commitId Commit identifier 53 | * @param userId User identifier 54 | * @param date Commit date 55 | * @param comment Commit comment 56 | * @return Commit metadata instance 57 | */ 58 | CommitMetadata createCommitMetadata(CommitId commitId, UserId userId, Date date, String comment); 59 | 60 | /** 61 | * Create an instance of change details 62 | * 63 | * @param revisionTag Revision tag 64 | * @param changeSubject Change subject 65 | * @param changeType Change type 66 | * @param property Annotation property that has been changed (optional) 67 | * @param newValue New value of the annotation property (optional) 68 | * @return Change details instance 69 | */ 70 | ChangeDetails createChangeDetails(RevisionTag revisionTag, OWLObject changeSubject, ChangeType changeType, 71 | Optional property, Optional newValue); 72 | 73 | /** 74 | * Create an instance of a revision tag 75 | * 76 | * @param revisionTag Revision tag 77 | * @return Revision tag instance 78 | */ 79 | RevisionTag createRevisionTag(String revisionTag); 80 | 81 | /** 82 | * Generate a random change identifier that is a UUID 83 | * 84 | * @return Change identifier 85 | */ 86 | ChangeId createChangeId(); 87 | 88 | /** 89 | * Generate a change identifier 90 | * 91 | * @param changeId Change identifier 92 | * @return Change identifier 93 | */ 94 | ChangeId createChangeId(String changeId); 95 | 96 | /** 97 | * Create a change review instance 98 | * 99 | * @param status Review status 100 | * @param author User identifier of reviewer 101 | * @param date Review date 102 | * @param comment Review-commit comment 103 | * @param isCommitted true of the review has been committed, false otherwise 104 | * @return Review instance 105 | */ 106 | Review createReview(ReviewStatus status, Optional author, Optional date, Optional comment, boolean isCommitted); 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/action/ShowStatusAction.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.action; 2 | 3 | import org.protege.editor.core.ui.error.ErrorLogPanel; 4 | import org.protege.editor.owl.client.connect.ServerConnectionManager; 5 | import org.protege.editor.owl.model.event.OWLModelManagerChangeEvent; 6 | import org.protege.editor.owl.model.event.OWLModelManagerListener; 7 | import org.protege.editor.owl.ui.UIHelper; 8 | import org.protege.editor.owl.ui.action.ProtegeOWLAction; 9 | import org.protege.owl.server.api.RevisionPointer; 10 | import org.protege.owl.server.api.client.Client; 11 | import org.protege.owl.server.api.client.VersionedOntologyDocument; 12 | import org.protege.owl.server.api.exception.UserDeclinedAuthenticationException; 13 | import org.protege.owl.server.util.ClientUtilities; 14 | import org.semanticweb.owlapi.model.OWLOntology; 15 | 16 | import javax.swing.*; 17 | import java.awt.*; 18 | import java.awt.event.ActionEvent; 19 | 20 | public class ShowStatusAction extends ProtegeOWLAction { 21 | private static final long serialVersionUID = 4601012273632698091L; 22 | private ServerConnectionManager connectionManager; 23 | private OWLModelManagerListener listener = new OWLModelManagerListener() { 24 | @Override 25 | public void handleChange(OWLModelManagerChangeEvent event) { 26 | updateEnabled(); 27 | } 28 | }; 29 | 30 | @Override 31 | public void initialise() throws Exception { 32 | updateEnabled(); 33 | getOWLModelManager().addListener(listener); 34 | } 35 | 36 | private void updateEnabled() { 37 | connectionManager = ServerConnectionManager.get(getOWLEditorKit()); 38 | OWLOntology ontology = getOWLEditorKit().getModelManager().getActiveOntology(); 39 | VersionedOntologyDocument vont = connectionManager.getVersionedOntology(ontology); 40 | if (vont == null) { 41 | setEnabled(false); 42 | } else { 43 | setEnabled(true); 44 | } 45 | } 46 | 47 | @Override 48 | public void dispose() throws Exception { 49 | getOWLModelManager().removeListener(listener); 50 | } 51 | 52 | @Override 53 | public void actionPerformed(ActionEvent arg0) { 54 | try { 55 | final OWLOntology ontology = getOWLEditorKit().getModelManager().getActiveOntology(); 56 | final VersionedOntologyDocument vont = connectionManager.getVersionedOntology(ontology); 57 | Client client = connectionManager.createClient(ontology); 58 | JDialog dialog = new JDialog(); 59 | dialog.setTitle("Client status"); 60 | dialog.setLocationRelativeTo(getOWLWorkspace()); 61 | 62 | JPanel panel = new JPanel(new GridLayout(0,2)); 63 | 64 | panel.add(new JLabel("Server Document:")); 65 | panel.add(new JLabel(vont.getServerDocument().getServerLocation().toString())); 66 | 67 | panel.add(new JLabel("Local Revision:")); 68 | panel.add(new JLabel(vont.getRevision().toString())); 69 | 70 | panel.add(new JLabel("Latest Server Revision:")); 71 | panel.add(new JLabel(client.evaluateRevisionPointer(vont.getServerDocument(), RevisionPointer.HEAD_REVISION).toString())); 72 | 73 | panel.add(new JLabel("# of uncommitted changes:")); 74 | panel.add(new JLabel("" + ClientUtilities.getUncommittedChanges(client, vont).size())); 75 | 76 | dialog.getContentPane().setLayout(new BorderLayout()); 77 | dialog.getContentPane().add(panel, BorderLayout.CENTER); 78 | dialog.pack(); 79 | dialog.setVisible(true); 80 | 81 | } 82 | catch (UserDeclinedAuthenticationException udae) { 83 | ; // ignore this because the user knows that he didn't want to authenticate 84 | } 85 | catch (Exception e) { 86 | ErrorLogPanel.showErrorDialog(e); 87 | UIHelper ui = new UIHelper(getOWLEditorKit()); 88 | ui.showDialog("Error connecting to server", new JLabel("Commit failed - " + e.getMessage())); 89 | } 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/AxiomChangeAnnotator.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | import org.apache.log4j.Logger; 6 | import org.semanticweb.owlapi.apibinding.OWLManager; 7 | import org.semanticweb.owlapi.model.*; 8 | import org.semanticweb.owlapi.vocab.OWL2Datatype; 9 | 10 | import java.util.*; 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 final class AxiomChangeAnnotator implements OwlOntologyChangeAnnotator { 19 | private static final Logger log = Logger.getLogger(AxiomChangeAnnotator.class); 20 | public static final IRI PROPERTY_IRI = IRI.create("http://protege.stanford.edu/ontology/hasChangeType"); 21 | public static final String SEPARATOR = "|:|", ALT_SEPARATOR = "]:["; 22 | private final OWLDataFactory df = OWLManager.getOWLDataFactory(); 23 | 24 | /** 25 | * Constructor 26 | */ 27 | public AxiomChangeAnnotator() { } 28 | 29 | @Override 30 | public List getAnnotatedChange(List changes, RevisionTag revisionTag, OWLEntity changeSubject, ChangeType changeType, Optional p, Optional newValue) { 31 | checkNotNull(changes); 32 | checkNotNull(revisionTag); 33 | checkNotNull(changeSubject); 34 | checkNotNull(changeType); 35 | List annotatedChanges = new ArrayList<>(); 36 | OWLAnnotationProperty property = df.getOWLAnnotationProperty(PROPERTY_IRI); 37 | for(OWLOntologyChange change : changes) { 38 | if(change.isAxiomChange()) { 39 | OWLAxiom axiom = change.getAxiom(); 40 | OWLAnnotation annotation = df.getOWLAnnotation(property, 41 | df.getOWLLiteral( 42 | revisionTag.getTag() + SEPARATOR + 43 | changeSubject.getIRI().toString() + SEPARATOR + 44 | changeType.getDisplayName() + (changeType.getDisplayColor().isPresent() ? ALT_SEPARATOR + changeType.getDisplayColor().get().getRGB() : "") + SEPARATOR + 45 | (p.isPresent() ? p.get().getIRI() : "") + SEPARATOR + 46 | (newValue.isPresent() ? newValue.get() : ""), 47 | OWL2Datatype.XSD_STRING 48 | )); 49 | Set annotations = new HashSet<>(); 50 | annotations.add(annotation); 51 | 52 | OWLOntologyChange annotatedChange; 53 | if(change.isAddAxiom()) { 54 | annotatedChange = new AddAxiom(change.getOntology(), axiom.getAnnotatedAxiom(annotations)); 55 | } 56 | else { 57 | annotatedChange = new RemoveAxiom(change.getOntology(), axiom.getAnnotatedAxiom(annotations)); 58 | } 59 | annotatedChanges.add(annotatedChange); 60 | } 61 | else { 62 | log.error("Non-axiom change ignored (non-axiom changes are not allowed in the axiom change annotator):\n\t" + change); 63 | } 64 | } 65 | return annotatedChanges; 66 | } 67 | 68 | public static String getSeparatorRegex() { 69 | return SEPARATOR.replaceAll("\\|", "\\\\|"); 70 | } 71 | 72 | public static String getAltSeparatorRegex() { 73 | return ALT_SEPARATOR.replaceAll("\\[", "\\\\["); 74 | } 75 | 76 | @Override 77 | public boolean equals(Object o) { 78 | if (this == o) return true; 79 | if (o == null || getClass() != o.getClass()) return false; 80 | AxiomChangeAnnotator that = (AxiomChangeAnnotator) o; 81 | return Objects.equal(df, that.df); 82 | } 83 | 84 | @Override 85 | public int hashCode() { 86 | return Objects.hashCode(df); 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return MoreObjects.toStringHelper(this) 92 | .add("df", df) 93 | .toString(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangesTableModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.client.diff.model.*; 4 | import org.protege.owl.server.api.UserId; 5 | import org.semanticweb.owlapi.model.OWLObject; 6 | 7 | import javax.swing.table.AbstractTableModel; 8 | import java.util.ArrayList; 9 | import java.util.Date; 10 | import java.util.List; 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 ChangesTableModel extends AbstractTableModel { 19 | private static final long serialVersionUID = -2515070763652227164L; 20 | private List changes = new ArrayList<>(); 21 | 22 | /** 23 | * No-args constructor 24 | */ 25 | public ChangesTableModel() { } 26 | 27 | public void setChanges(List changes) { 28 | this.changes = checkNotNull(changes); 29 | fireTableDataChanged(); 30 | } 31 | 32 | @Override 33 | public int getRowCount() { 34 | return (changes != null ? changes.size() : 0); 35 | } 36 | 37 | @Override 38 | public int getColumnCount() { 39 | return Column.values().length; 40 | } 41 | 42 | @Override 43 | public Object getValueAt(int rowIndex, int columnIndex) { 44 | Change change = getChange(rowIndex); 45 | switch (Column.values()[columnIndex]) { 46 | case MODE: 47 | return change.getMode(); 48 | case DATE: 49 | return change.getCommitMetadata().getDate(); 50 | case AUTHOR: 51 | return change.getCommitMetadata().getAuthor(); 52 | case CHANGE_SUBJECT: 53 | return change.getDetails().getSubject(); 54 | case CHANGE_TYPE: 55 | return change.getDetails().getType(); 56 | case REVISION_TAG: 57 | return change.getDetails().getRevisionTag().getTag(); 58 | case COMMENT: 59 | return change.getCommitMetadata().getComment(); 60 | case CONFLICT: 61 | return change.isConflicting(); 62 | case REVIEW: 63 | return change.getReview(); 64 | default: 65 | throw new IllegalStateException(); 66 | } 67 | } 68 | 69 | public Change getChange(int rowIndex) { 70 | return changes.get(rowIndex); 71 | } 72 | 73 | @Override 74 | public Class getColumnClass(int columnIndex) { 75 | Column col = Column.values()[columnIndex]; 76 | switch (col) { 77 | case DATE: 78 | return Date.class; 79 | case AUTHOR: 80 | return UserId.class; 81 | case MODE: 82 | return ChangeMode.class; 83 | case COMMENT: 84 | return String.class; 85 | case CHANGE_TYPE: 86 | return ChangeType.class; 87 | case CHANGE_SUBJECT: 88 | return OWLObject.class; 89 | case CONFLICT: 90 | return Boolean.class; 91 | case REVIEW: 92 | return Review.class; 93 | case REVISION_TAG: 94 | return String.class; 95 | default: 96 | throw new IllegalStateException("Programmer Error: a case was missed"); 97 | } 98 | } 99 | 100 | public String getColumnName(int column) { 101 | return Column.values()[column].toString(); 102 | } 103 | 104 | public void clear() { 105 | changes.clear(); 106 | } 107 | 108 | public enum Column { 109 | MODE("Mode"), 110 | DATE("Date"), 111 | AUTHOR("Author"), 112 | CHANGE_SUBJECT("Change Subject"), 113 | CHANGE_TYPE("Type"), 114 | REVISION_TAG("Revision Tag"), 115 | COMMENT("Comment"), 116 | CONFLICT("Conflict"), 117 | REVIEW("Review"); 118 | 119 | private String name; 120 | 121 | Column(String name) { 122 | this.name = checkNotNull(name); 123 | } 124 | 125 | @Override 126 | public String toString() { 127 | return name; 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangesTableCellRenderer.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.ui; 2 | 3 | import org.protege.editor.owl.OWLEditorKit; 4 | import org.protege.editor.owl.client.diff.model.ChangeMode; 5 | import org.protege.editor.owl.client.diff.model.ChangeType; 6 | import org.protege.editor.owl.client.diff.model.Review; 7 | import org.semanticweb.owlapi.model.OWLObject; 8 | 9 | import javax.swing.*; 10 | import java.awt.*; 11 | import java.util.Date; 12 | 13 | /** 14 | * @author Rafael Gonçalves
15 | * Stanford Center for Biomedical Informatics Research 16 | */ 17 | public class ChangesTableCellRenderer extends LogDiffCellRenderer { 18 | 19 | /** 20 | * Constructor 21 | * 22 | * @param editorKit OWL editor kit 23 | */ 24 | public ChangesTableCellRenderer(OWLEditorKit editorKit) { 25 | super(editorKit); 26 | } 27 | 28 | @Override 29 | public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 30 | // coordinates passed to the renderer are in view coordinate system after sorting, so they need converting to model coordinates before accessing the model 31 | int modelRow = table.convertRowIndexToModel(row); 32 | ChangeMode mode = (ChangeMode) table.getModel().getValueAt(modelRow, ChangesTableModel.Column.MODE.ordinal()); 33 | ChangeType type = (ChangeType) table.getModel().getValueAt(modelRow, ChangesTableModel.Column.CHANGE_TYPE.ordinal()); 34 | if (value instanceof OWLObject) { 35 | Component c = owlCellRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 36 | setBackground(table, type, mode, c, isSelected); 37 | return c; 38 | } 39 | if(value instanceof Boolean) { 40 | if((Boolean)value) { 41 | return getIconLabel(table, type, mode, GuiUtils.WARNING_ICON_FILENAME, isSelected, true); 42 | } else { 43 | value = null; 44 | } 45 | } 46 | if(value != null && value instanceof Review) { 47 | Review review = (Review) value; 48 | switch(review.getStatus()) { 49 | case ACCEPTED: 50 | return getIconLabel(table, type, mode, GuiUtils.REVIEW_ACCEPTED_ICON_FILENAME, isSelected, review.isCommitted()); 51 | case REJECTED: 52 | return getIconLabel(table, type, mode, GuiUtils.REVIEW_REJECTED_ICON_FILENAME, isSelected, review.isCommitted()); 53 | case PENDING: 54 | default: 55 | value = ""; 56 | } 57 | } 58 | if(value instanceof Date) { 59 | setText(GuiUtils.getFormattedDate((Date)value)); 60 | } 61 | else { 62 | setText(value != null ? value.toString() : ""); 63 | } 64 | setBackground(table, type, mode, this, isSelected); 65 | setFont(table.getFont()); 66 | return this; 67 | } 68 | 69 | private void setBackground(JTable table, ChangeType type, ChangeMode mode, Component c, boolean isSelected) { 70 | if (isSelected) { 71 | c.setBackground(table.getSelectionBackground()); 72 | c.setForeground(table.getSelectionForeground()); 73 | } 74 | else if(type.getDisplayColor().isPresent()) { 75 | c.setBackground(type.getDisplayColor().get()); 76 | c.setForeground(GuiUtils.UNSELECTED_FOREGROUND); 77 | } 78 | else { 79 | GuiUtils.setComponentBackground(c, mode); 80 | c.setForeground(GuiUtils.UNSELECTED_FOREGROUND); 81 | } 82 | } 83 | 84 | private JLabel getIconLabel(JTable table, ChangeType type, ChangeMode mode, String iconFilename, boolean isSelected, boolean committed) { 85 | Icon icon = GuiUtils.getIcon(iconFilename, 25, 25); 86 | // rpc 87 | // if(!committed) { 88 | // ImageIcon base = (ImageIcon)GuiUtils.getIcon(iconFilename, 30, 30); 89 | // ImageIcon badge = (ImageIcon) GuiUtils.getIcon(GuiUtils.NEW_REVIEW_ICON_FILENAME, 13, 13); 90 | // BufferedImage img = new BufferedImage(30, 30, AlphaComposite.SRC_OVER); 91 | // Graphics g = img.getGraphics(); 92 | // g.drawImage(base.getImage(), 0, 0, null); 93 | // g.drawImage(badge.getImage(), 17, 0, null); 94 | // icon = new ImageIcon(img); 95 | // } 96 | JLabel lbl = new JLabel("", icon, JLabel.CENTER); 97 | lbl.setOpaque(true); 98 | setBackground(table, type, mode, lbl, isSelected); 99 | return lbl; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/AuthorPanel.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.LogDiffEvent; 6 | import org.protege.editor.owl.client.diff.model.LogDiffManager; 7 | import org.protege.editor.owl.model.OWLModelManager; 8 | import org.protege.editor.owl.model.event.EventType; 9 | import org.protege.editor.owl.model.event.OWLModelManagerListener; 10 | import org.protege.owl.server.api.ChangeHistory; 11 | import org.protege.owl.server.api.ChangeMetaData; 12 | import org.protege.owl.server.api.OntologyDocumentRevision; 13 | import org.protege.owl.server.api.UserId; 14 | import org.protege.owl.server.api.client.VersionedOntologyDocument; 15 | import org.semanticweb.owlapi.model.OWLOntologyChangeListener; 16 | 17 | import javax.swing.*; 18 | import javax.swing.event.ListSelectionListener; 19 | import java.awt.*; 20 | import java.util.ArrayList; 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | /** 25 | * @author Rafael Gonçalves
26 | * Stanford Center for Biomedical Informatics Research 27 | */ 28 | public class AuthorPanel extends JPanel implements Disposable { 29 | private static final long serialVersionUID = -211414461074963460L; 30 | private OWLModelManager modelManager; 31 | private LogDiffManager diffManager; 32 | private JList authorsList = new JList<>(); 33 | 34 | /** 35 | * Constructor 36 | * 37 | * @param modelManager OWL model manager 38 | * @param editorKit OWL editor kit 39 | */ 40 | public AuthorPanel(OWLModelManager modelManager, OWLEditorKit editorKit) { 41 | this.modelManager = modelManager; 42 | diffManager = LogDiffManager.get(modelManager, editorKit); 43 | setLayout(new BorderLayout(20, 20)); 44 | setupList(); 45 | 46 | // listeners 47 | modelManager.getOWLOntologyManager().addOntologyChangeListener(ontologyChangeListener); 48 | modelManager.addListener(ontologyLoadListener); 49 | 50 | JScrollPane scrollPane = new JScrollPane(authorsList); 51 | scrollPane.setBorder(GuiUtils.EMPTY_BORDER); 52 | add(scrollPane, BorderLayout.CENTER); 53 | listAuthors(); 54 | } 55 | 56 | private ListSelectionListener listSelectionListener = e -> { 57 | UserId selection = authorsList.getSelectedValue(); 58 | if (selection != null && !e.getValueIsAdjusting()) { 59 | diffManager.setSelectedAuthor(selection); 60 | } 61 | }; 62 | 63 | private OWLOntologyChangeListener ontologyChangeListener = changes -> { 64 | diffManager.clearSelections(); 65 | listAuthors(); 66 | diffManager.statusChanged(LogDiffEvent.ONTOLOGY_UPDATED); 67 | }; 68 | 69 | private OWLModelManagerListener ontologyLoadListener = event -> { 70 | if(event.isType(EventType.ONTOLOGY_LOADED) || event.isType(EventType.ACTIVE_ONTOLOGY_CHANGED)) { 71 | diffManager.clearSelections(); 72 | listAuthors(); 73 | diffManager.statusChanged(LogDiffEvent.ONTOLOGY_UPDATED); 74 | } 75 | }; 76 | 77 | private void setupList() { 78 | authorsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 79 | authorsList.addListSelectionListener(listSelectionListener); 80 | authorsList.setCellRenderer(new AuthorListCellRenderer()); 81 | authorsList.setFixedCellHeight(35); 82 | authorsList.setBorder(GuiUtils.MATTE_BORDER); 83 | } 84 | 85 | private void listAuthors() { 86 | if(diffManager.getVersionedOntologyDocument().isPresent()) { 87 | VersionedOntologyDocument vont = diffManager.getVersionedOntologyDocument().get(); 88 | ChangeHistory changes = vont.getLocalHistory(); 89 | List users = new ArrayList<>(); 90 | OntologyDocumentRevision rev = changes.getStartRevision(); 91 | while (changes.getMetaData(rev) != null) { 92 | ChangeMetaData metaData = changes.getMetaData(rev); 93 | UserId user = metaData.getUserId(); 94 | if (!users.contains(user)) { 95 | users.add(user); 96 | } 97 | rev = rev.next(); 98 | } 99 | Collections.sort(users); 100 | users.add(0, LogDiffManager.ALL_AUTHORS); 101 | authorsList.setListData(users.toArray(new UserId[users.size()])); 102 | } 103 | else { 104 | authorsList.setListData(new UserId[0]); 105 | } 106 | } 107 | 108 | @Override 109 | public void dispose() { 110 | modelManager.removeListener(ontologyLoadListener); 111 | modelManager.getOWLOntologyManager().removeOntologyChangeListener(ontologyChangeListener); 112 | authorsList.removeListSelectionListener(listSelectionListener); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/action/CommitAction.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.action; 2 | 3 | import org.protege.editor.core.ui.error.ErrorLogPanel; 4 | import org.protege.editor.owl.client.connect.ServerConnectionManager; 5 | import org.protege.editor.owl.model.event.OWLModelManagerChangeEvent; 6 | import org.protege.editor.owl.model.event.OWLModelManagerListener; 7 | import org.protege.editor.owl.ui.UIHelper; 8 | import org.protege.editor.owl.ui.action.ProtegeOWLAction; 9 | import org.protege.owl.server.api.ChangeMetaData; 10 | import org.protege.owl.server.api.client.Client; 11 | import org.protege.owl.server.api.client.VersionedOntologyDocument; 12 | import org.protege.owl.server.api.exception.OWLServerException; 13 | import org.protege.owl.server.api.exception.UserDeclinedAuthenticationException; 14 | import org.protege.owl.server.util.ClientUtilities; 15 | import org.semanticweb.owlapi.model.OWLOntology; 16 | 17 | import javax.swing.*; 18 | import java.awt.*; 19 | import java.awt.event.ActionEvent; 20 | 21 | public class CommitAction extends ProtegeOWLAction { 22 | private static final long serialVersionUID = 4601012273632698091L; 23 | private ServerConnectionManager connectionManager; 24 | private OWLModelManagerListener listener = new OWLModelManagerListener() { 25 | @Override 26 | public void handleChange(OWLModelManagerChangeEvent event) { 27 | updateEnabled(); 28 | } 29 | }; 30 | 31 | @Override 32 | public void initialise() throws Exception { 33 | updateEnabled(); 34 | getOWLModelManager().addListener(listener); 35 | } 36 | 37 | private void updateEnabled() { 38 | connectionManager = ServerConnectionManager.get(getOWLEditorKit()); 39 | OWLOntology ontology = getOWLEditorKit().getModelManager().getActiveOntology(); 40 | VersionedOntologyDocument vont = connectionManager.getVersionedOntology(ontology); 41 | if (vont == null) { 42 | setEnabled(false); 43 | } else { 44 | setEnabled(true); 45 | } 46 | } 47 | 48 | @Override 49 | public void dispose() throws Exception { 50 | getOWLModelManager().removeListener(listener); 51 | } 52 | 53 | @Override 54 | public void actionPerformed(ActionEvent arg0) { 55 | try { 56 | Container owner = SwingUtilities.getAncestorOfClass(Frame.class,getOWLWorkspace()); 57 | final OWLOntology ontology = getOWLEditorKit().getModelManager().getActiveOntology(); 58 | final VersionedOntologyDocument vont = connectionManager.getVersionedOntology(ontology); 59 | final String commitComment = JOptionPane.showInputDialog(owner, "Commit comment: ", "Commit", JOptionPane.PLAIN_MESSAGE); 60 | if (vont == null) { 61 | JOptionPane.showMessageDialog(owner, "Commit ignored because the ontology is not associated with a server"); 62 | return; 63 | } 64 | if(commitComment == null) { 65 | return; // user pressed cancel 66 | } 67 | Client client = connectionManager.createClient(ontology); 68 | 69 | // TODO MetaData should not accept null commit comment.. 70 | connectionManager.getSingleThreadExecutorService().submit(new DoCommit(client, vont, (!commitComment.isEmpty() ? commitComment : ""))); 71 | } 72 | catch (UserDeclinedAuthenticationException udae) { 73 | ; // ignore this because the user knows that he didn't want to authenticate 74 | } 75 | catch (Exception e) { 76 | handleError(e); 77 | } 78 | 79 | } 80 | 81 | // ToDo modify the synchronization so that this can run in the background 82 | // even while edits are in progress. 83 | // make this part of the utility? 84 | private class DoCommit implements Runnable { 85 | private Client client; 86 | private VersionedOntologyDocument vont; 87 | private String commitcomment; 88 | public DoCommit(Client client, VersionedOntologyDocument vont, String commitComment) { 89 | this.client = client; 90 | this.vont = vont; 91 | this.commitcomment = commitComment; 92 | } 93 | 94 | @Override 95 | public void run() { 96 | ChangeMetaData metaData = new ChangeMetaData(commitcomment); 97 | try { 98 | ClientUtilities.commit(client, metaData, vont); 99 | } 100 | catch (OWLServerException ose) { 101 | handleError(ose); 102 | } 103 | catch (Error e) { 104 | handleError(e); 105 | } 106 | catch (RuntimeException re) { 107 | handleError(re); 108 | } 109 | } 110 | } 111 | 112 | private void handleError(Throwable t) { 113 | ErrorLogPanel.showErrorDialog(t); 114 | UIHelper ui = new UIHelper(getOWLEditorKit()); 115 | ui.showDialog("Error connecting to server", new JLabel("Commit failed - " + t.getMessage())); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/ui/ChangesPanel.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.event.ListSelectionListener; 10 | import javax.swing.table.TableColumn; 11 | import javax.swing.table.TableModel; 12 | import javax.swing.table.TableRowSorter; 13 | import java.awt.*; 14 | import java.util.ArrayList; 15 | import java.util.Collections; 16 | import java.util.List; 17 | 18 | import static com.google.common.base.Preconditions.checkNotNull; 19 | 20 | /** 21 | * @author Rafael Gonçalves
22 | * Stanford Center for Biomedical Informatics Research 23 | */ 24 | public class ChangesPanel extends JPanel implements Disposable { 25 | private OWLEditorKit editorKit; 26 | private LogDiffManager diffManager; 27 | private ChangesTableModel diffTableModel; 28 | private JTable table; 29 | private LogDiff diff; 30 | 31 | /** 32 | * Constructor 33 | * 34 | * @param modelManager OWL model manager 35 | * @param editorKit OWL editor kit 36 | */ 37 | public ChangesPanel(OWLModelManager modelManager, OWLEditorKit editorKit) { 38 | this.editorKit = checkNotNull(editorKit); 39 | diffManager = LogDiffManager.get(modelManager, editorKit); 40 | diffManager.addListener(diffListener); 41 | diff = diffManager.getDiffEngine(); 42 | 43 | setLayout(new BorderLayout()); 44 | setBorder(GuiUtils.MATTE_BORDER); 45 | 46 | createDiffTable(); 47 | } 48 | 49 | private ListSelectionListener rowSelectionListener = e -> { 50 | if (e.getValueIsAdjusting()) { 51 | return; 52 | } 53 | ListSelectionModel lsm = (ListSelectionModel)e.getSource(); 54 | if (!lsm.isSelectionEmpty()) { 55 | List selectedChanges = new ArrayList<>(); 56 | for(int i = 0; i < table.getSelectedRowCount(); i++) { 57 | Change change = diffTableModel.getChange(table.convertRowIndexToModel(table.getSelectedRows()[i])); 58 | selectedChanges.add(change); 59 | } 60 | diffManager.setSelectedChanges(selectedChanges); 61 | } 62 | }; 63 | 64 | private LogDiffListener diffListener = new LogDiffListener() { 65 | @Override 66 | public void statusChanged(LogDiffEvent event) { 67 | if(event.equals(LogDiffEvent.AUTHOR_SELECTION_CHANGED) || event.equals(LogDiffEvent.COMMIT_SELECTION_CHANGED)) { 68 | diffManager.clearSelectedChanges(); 69 | updateDiff(event); 70 | } 71 | else if(event.equals(LogDiffEvent.ONTOLOGY_UPDATED)) { // TODO incrementally update change indices 72 | diff.clear(); 73 | diff.initDiff(); 74 | diffTableModel.setChanges(Collections.emptyList()); 75 | } 76 | else if(event.equals(LogDiffEvent.CHANGE_REVIEWED)) { 77 | revalidate(); repaint(); 78 | } 79 | else if(event.equals(LogDiffEvent.RESET)) { 80 | diffTableModel.clear(); 81 | } 82 | } 83 | }; 84 | 85 | private void updateDiff(LogDiffEvent event) { 86 | if(diff.getChanges().isEmpty()) { 87 | diff.initDiff(); 88 | } 89 | List changesToDisplay = diff.getChangesToDisplay(event); 90 | Collections.sort(changesToDisplay); 91 | diffTableModel.setChanges(changesToDisplay); 92 | } 93 | 94 | private void createDiffTable() { 95 | // create diff table model 96 | diffTableModel = new ChangesTableModel(); 97 | 98 | // create diff table 99 | table = new ChangesTable(diffTableModel, editorKit); 100 | setColumnsWidth(table, 3, 13, 15, 15, 10, 7, 27, 5, 5); 101 | 102 | JScrollPane scrollPane = new JScrollPane(table); 103 | scrollPane.setBorder(GuiUtils.EMPTY_BORDER); 104 | add(scrollPane, BorderLayout.CENTER); 105 | table.getSelectionModel().addListSelectionListener(rowSelectionListener); 106 | 107 | // allow sorting columns (sort initially by the date column) 108 | TableRowSorter sorter = new TableRowSorter<>(diffTableModel); 109 | List sortKeys = new ArrayList<>(); 110 | sortKeys.add(new RowSorter.SortKey(ChangesTableModel.Column.DATE.ordinal(), SortOrder.DESCENDING)); 111 | sorter.setSortKeys(sortKeys); 112 | table.setRowSorter(sorter); 113 | } 114 | 115 | private void setColumnsWidth(JTable table, double... values) { 116 | for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) { 117 | TableColumn column = table.getColumnModel().getColumn(i); 118 | column.setPreferredWidth((int)values[i]*100); 119 | } 120 | } 121 | 122 | @Override 123 | public void dispose() { 124 | diffManager.removeListener(diffListener); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ReviewManagerImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | import org.semanticweb.owlapi.model.*; 6 | 7 | import java.util.*; 8 | import java.util.stream.Collectors; 9 | 10 | import static com.google.common.base.Preconditions.checkNotNull; 11 | 12 | /** 13 | * @author Rafael Gonçalves
14 | * Stanford Center for Biomedical Informatics Research 15 | */ 16 | public class ReviewManagerImpl implements ReviewManager { 17 | private Map newReviews = new HashMap<>(); 18 | private Map reviews = new HashMap<>(); 19 | private LogDiff diff; 20 | 21 | /** 22 | * Constructor 23 | * 24 | * @param diff Log diff engine 25 | */ 26 | public ReviewManagerImpl(LogDiff diff) { 27 | this.diff = checkNotNull(diff); 28 | } 29 | 30 | @Override 31 | public void setReviewStatus(Change c, ReviewStatus status) { 32 | checkNotNull(c); checkNotNull(status); 33 | 34 | // gather initial status of the newly reviewed change 35 | if(!newReviews.containsKey(c.getId())) { 36 | reviews.put(c.getId(), c.getReviewStatus()); 37 | } 38 | 39 | // if new review does not differ from initial state, no real review change occurred 40 | if(reviews.get(c.getId()).equals(status)) { 41 | newReviews.remove(c.getId()); 42 | } else { 43 | newReviews.put(c.getId(), status); 44 | } 45 | c.setReviewStatus(status); 46 | } 47 | 48 | @Override 49 | public boolean reviewChanged(Change c) { 50 | if(reviews.get(c.getId()) != null && newReviews.get(c.getId()) != null) { 51 | if (!reviews.get(c.getId()).equals(newReviews.get(c.getId()))) { 52 | return true; 53 | } 54 | } 55 | return false; 56 | } 57 | 58 | @Override 59 | public boolean hasUncommittedReviews() { 60 | return !newReviews.isEmpty(); 61 | } 62 | 63 | @Override 64 | public List getReviewOntologyChanges() { 65 | List changes = new ArrayList<>(); 66 | for(ChangeId id : newReviews.keySet()) { 67 | Change c = diff.getChange(id); 68 | if(newReviews.get(c.getId()).equals(ReviewStatus.REJECTED)) { 69 | Set ontChanges = c.getChanges(); 70 | if (c.getBaselineChange().isPresent()) { 71 | OWLOntologyChange baseline = c.getBaselineChange().get(); 72 | changes.add(getReverseChange(baseline)); 73 | } 74 | changes.addAll(ontChanges.stream().map(this::getReverseChange).collect(Collectors.toList())); 75 | } 76 | } 77 | return changes; 78 | } 79 | 80 | private OWLOntologyChange getReverseChange(OWLOntologyChange change) { 81 | if(change.isAxiomChange()) { 82 | if (change.isAddAxiom()) { 83 | return new RemoveAxiom(change.getOntology(), change.getAxiom()); 84 | } 85 | else if(change.isRemoveAxiom()) { 86 | return new AddAxiom(change.getOntology(), change.getAxiom()); 87 | } 88 | } 89 | else if(change.isImportChange()) { 90 | if(change instanceof AddImport) { 91 | return new RemoveImport(change.getOntology(), ((ImportChange)change).getImportDeclaration()); 92 | } 93 | else if(change instanceof RemoveImport) { 94 | return new AddImport(change.getOntology(), ((ImportChange)change).getImportDeclaration()); 95 | } 96 | } 97 | else if (change instanceof AnnotationChange) { 98 | if(change instanceof AddOntologyAnnotation) { 99 | return new RemoveOntologyAnnotation(change.getOntology(), ((AnnotationChange)change).getAnnotation()); 100 | } 101 | else if(change instanceof RemoveOntologyAnnotation) { 102 | return new AddOntologyAnnotation(change.getOntology(), ((AnnotationChange)change).getAnnotation()); 103 | } 104 | } 105 | else if(change instanceof SetOntologyID) { 106 | return new SetOntologyID(change.getOntology(), ((SetOntologyID)change).getOriginalOntologyID().getOntologyIRI().get()); 107 | } 108 | return null; 109 | } 110 | 111 | @Override 112 | public void clearUncommittedReviews() { 113 | for(ChangeId id : newReviews.keySet()) { 114 | Change c = diff.getChange(id); 115 | c.setReviewStatus(ReviewStatus.PENDING); 116 | } 117 | newReviews.clear(); 118 | } 119 | 120 | @Override 121 | public boolean equals(Object o) { 122 | if (this == o) return true; 123 | if (o == null || getClass() != o.getClass()) return false; 124 | ReviewManagerImpl that = (ReviewManagerImpl) o; 125 | return Objects.equal(newReviews, that.newReviews) && 126 | Objects.equal(reviews, that.reviews); 127 | } 128 | 129 | @Override 130 | public int hashCode() { 131 | return Objects.hashCode(newReviews, reviews); 132 | } 133 | 134 | @Override 135 | public String toString() { 136 | return MoreObjects.toStringHelper(this) 137 | .add("newReviews", newReviews) 138 | .add("reviews", reviews) 139 | .toString(); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/panel/ChangeListTableModel.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.panel; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import javax.swing.table.AbstractTableModel; 7 | 8 | import org.protege.owl.server.api.ChangeMetaData; 9 | import org.semanticweb.owlapi.model.AddAxiom; 10 | import org.semanticweb.owlapi.model.AddImport; 11 | import org.semanticweb.owlapi.model.AddOntologyAnnotation; 12 | import org.semanticweb.owlapi.model.OWLObject; 13 | import org.semanticweb.owlapi.model.OWLOntologyChange; 14 | import org.semanticweb.owlapi.model.OWLOntologyChangeVisitor; 15 | import org.semanticweb.owlapi.model.RemoveAxiom; 16 | import org.semanticweb.owlapi.model.RemoveImport; 17 | import org.semanticweb.owlapi.model.RemoveOntologyAnnotation; 18 | import org.semanticweb.owlapi.model.SetOntologyID; 19 | 20 | public class ChangeListTableModel extends AbstractTableModel { 21 | private static final long serialVersionUID = -3184570774482187890L; 22 | 23 | public enum Column { 24 | CHANGE_TYPE("Type") { 25 | @Override 26 | public Date getValue(ChangeMetaData metaData) { 27 | return metaData.getDate(); 28 | } 29 | }, 30 | ENTITY("Entity") { 31 | @Override 32 | public String getValue(ChangeMetaData metaData) { 33 | return metaData.getUserId().getUserName(); 34 | } 35 | }; 36 | 37 | private String name; 38 | 39 | 40 | private Column(String name) { 41 | this.name = name; 42 | } 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public abstract Object getValue(ChangeMetaData metaData); 49 | 50 | } 51 | 52 | private List changes; 53 | 54 | public ChangeListTableModel(List changes) { 55 | this.changes = changes; 56 | } 57 | 58 | public void setChangeList(List changes) { 59 | this.changes = changes; 60 | fireTableStructureChanged(); 61 | } 62 | 63 | @Override 64 | public int getColumnCount() { 65 | return Column.values().length; 66 | } 67 | 68 | @Override 69 | public int getRowCount() { 70 | return changes.size(); 71 | } 72 | 73 | @Override 74 | public Class getColumnClass(int columnIndex) { 75 | Column col = Column.values()[columnIndex]; 76 | switch (col) { 77 | case CHANGE_TYPE: 78 | return String.class; 79 | case ENTITY: 80 | return OWLObject.class; 81 | default: 82 | throw new IllegalStateException("Programmer Error: he missed a case."); 83 | } 84 | } 85 | 86 | @Override 87 | public String getColumnName(int column) { 88 | Column col = Column.values()[column]; 89 | return col.getName(); 90 | } 91 | 92 | @Override 93 | public Object getValueAt(int row, int column) { 94 | Column col = Column.values()[column]; 95 | OWLOntologyChange change = changes.get(row); 96 | RenderOntologyChangeVisitor visitor = new RenderOntologyChangeVisitor(); 97 | change.accept(visitor); 98 | switch (col) { 99 | case CHANGE_TYPE: 100 | return visitor.getChangeType(); 101 | case ENTITY: 102 | return visitor.getEntityChanged(); 103 | default: 104 | throw new IllegalStateException("Programmer error: he missed a case"); 105 | } 106 | 107 | } 108 | 109 | private static class RenderOntologyChangeVisitor implements OWLOntologyChangeVisitor { 110 | private String changeType; 111 | private OWLObject entityChanged; 112 | 113 | public String getChangeType() { 114 | return changeType; 115 | } 116 | 117 | public Object getEntityChanged() { 118 | return entityChanged; 119 | } 120 | 121 | 122 | @Override 123 | public void visit(AddAxiom change) { 124 | changeType = "Add Axiom"; 125 | entityChanged = change.getAxiom(); 126 | } 127 | @Override 128 | public void visit(RemoveAxiom change) { 129 | changeType = "Remove Axiom"; 130 | entityChanged = change.getAxiom(); 131 | } 132 | @Override 133 | public void visit(SetOntologyID change) { 134 | changeType = "Set Ontology Id"; 135 | entityChanged = change.getNewOntologyID().getDefaultDocumentIRI().get(); 136 | } 137 | @Override 138 | public void visit(AddImport change) { 139 | changeType = "Add Import"; 140 | entityChanged = change.getImportDeclaration().getIRI(); 141 | } 142 | @Override 143 | public void visit(RemoveImport change) { 144 | changeType = "Remove Import"; 145 | entityChanged = change.getImportDeclaration().getIRI(); 146 | } 147 | @Override 148 | public void visit(AddOntologyAnnotation change) { 149 | changeType = "Add Ontology Annotation"; 150 | entityChanged = change.getAnnotation(); 151 | } 152 | @Override 153 | public void visit(RemoveOntologyAnnotation change) { 154 | changeType = "Remove Ontology Annotation"; 155 | entityChanged = change.getAnnotation(); 156 | } 157 | 158 | 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/org/protege/editor/owl/client/diff/model/ChangeImpl.java: -------------------------------------------------------------------------------- 1 | package org.protege.editor.owl.client.diff.model; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import com.google.common.base.Objects; 5 | import com.google.common.collect.ComparisonChain; 6 | import org.semanticweb.owlapi.model.OWLOntologyChange; 7 | 8 | import java.util.HashSet; 9 | import java.util.Optional; 10 | import java.util.Set; 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 ChangeImpl implements Change { 19 | private final ChangeId id; 20 | private final Set changes; 21 | private final CommitMetadata commitMetadata; 22 | private ChangeMode mode; 23 | private ChangeDetails details; 24 | private Set conflictingChanges = new HashSet<>(); 25 | private OWLOntologyChange baselineChange; 26 | private Review review; 27 | 28 | 29 | /** 30 | * Constructor 31 | * 32 | * @param id Change identifier 33 | * @param changes Set of changes 34 | * @param details Change details 35 | * @param commitMetadata Commit metadata 36 | */ 37 | public ChangeImpl(ChangeId id, Set changes, ChangeDetails details, CommitMetadata commitMetadata, ChangeMode mode) { 38 | this.id = checkNotNull(id); 39 | this.changes = checkNotNull(changes); 40 | this.details = checkNotNull(details); 41 | this.commitMetadata = checkNotNull(commitMetadata); 42 | this.mode = checkNotNull(mode); 43 | } 44 | 45 | @Override 46 | public ChangeId getId() { 47 | return id; 48 | } 49 | 50 | @Override 51 | public Set getChanges() { 52 | return changes; 53 | } 54 | 55 | public ChangeDetails getDetails() { 56 | return details; 57 | } 58 | 59 | @Override 60 | public CommitMetadata getCommitMetadata() { 61 | return commitMetadata; 62 | } 63 | 64 | @Override 65 | public ChangeMode getMode() { 66 | return mode; 67 | } 68 | 69 | @Override 70 | public void setMode(ChangeMode mode) { 71 | this.mode = checkNotNull(mode); 72 | } 73 | 74 | @Override 75 | public boolean isOfType(ChangeType type) { 76 | return details.getType().equals(type); 77 | } 78 | 79 | @Override 80 | public void addConflictingChange(ChangeId conflictingChange) { 81 | this.conflictingChanges.add(checkNotNull(conflictingChange)); 82 | } 83 | 84 | @Override 85 | public Set getConflictingChanges() { 86 | return conflictingChanges; 87 | } 88 | 89 | @Override 90 | public boolean isConflicting() { 91 | return !conflictingChanges.isEmpty(); 92 | } 93 | 94 | @Override 95 | public void setReviewStatus(ReviewStatus reviewStatus) { 96 | review = LogDiffManager.getDiffFactory().createReview(reviewStatus, Optional.empty(), Optional.empty(), Optional.empty(), false); 97 | } 98 | 99 | @Override 100 | public ReviewStatus getReviewStatus() { 101 | if(review == null) { 102 | return ReviewStatus.PENDING; 103 | } 104 | else { 105 | return review.getStatus(); 106 | } 107 | } 108 | 109 | @Override 110 | public Review getReview() { 111 | return review; 112 | } 113 | 114 | @Override 115 | public void setReview(Review review) { 116 | this.review = checkNotNull(review); 117 | } 118 | 119 | @Override 120 | public Optional 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 | 15 | 16 | 17 | 18 | 20 | 25 | 26 | 28 | 33 | 34 | 36 | 41 | 42 | 44 | 49 | 50 | 52 | 57 | 58 | 60 | 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 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 | --------------------------------------------------------------------------------