/*
* Created on Apr 9, 2005
*
*/
package org.mindswap.swoop.change;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Vector;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.SpringLayout;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import org.mindswap.swoop.ModelChangeEvent;
import org.mindswap.swoop.SwoopModel;
import org.mindswap.swoop.SwoopModelListener;
import org.mindswap.swoop.annotea.Annotea;
import org.mindswap.swoop.annotea.AnnoteaClient;
import org.mindswap.swoop.annotea.Description;
import org.mindswap.swoop.renderer.ontology.OntologyListRenderer;
import org.mindswap.swoop.treetable.JTreeTable;
import org.mindswap.swoop.utils.change.BooleanElementChange;
import org.mindswap.swoop.utils.change.EnumElementChange;
import org.mindswap.swoop.utils.owlapi.CorrectedRDFRenderer;
import org.mindswap.swoop.utils.ui.ChangeComparator;
import org.mindswap.swoop.utils.ui.OntologyComparator;
import org.mindswap.swoop.utils.ui.SpringUtilities;
import org.mindswap.swoop.utils.ui.SwoopIcons;
import org.semanticweb.owl.model.OWLClass;
import org.semanticweb.owl.model.OWLEntity;
import org.semanticweb.owl.model.OWLException;
import org.semanticweb.owl.model.OWLOntology;
import org.semanticweb.owl.model.change.ChangeVisitor;
import org.semanticweb.owl.model.change.OntologyChange;
import org.semanticweb.owl.model.helper.OWLBuilder;
/**
* @author Aditya
*
*/
public class VersionedOntology extends JPanel implements ActionListener, KeyListener, TreeSelectionListener, HyperlinkListener, MouseListener, SwoopModelListener {
// constants
public static int ANNOTATED_CHANGES = 0;
public static String serverURL = "http://www.mindswap.org/2004/annotea/Annotation";
public static int REDUNDANT_CHANGE = 1;
public static int REPOSITORY_CHANGE = 2;
public static int LOCAL_CHANGE = 3;
public static String separator = "SWOOP-ANNOTATED-CHANGE-SET";
AnnoteaClient client;
OWLClass annotType;
SwoopModel swoopModel;
VersionControl controlHandler;
// repository info
URI repositoryURI;
String repositoryAuthor;
String reposityCreatedDate;
public URI baseOntologyURI;
public int headVersionNumber;
// versioning info
List repChanges; // only corresponds to new changes to be added to repository, (those already at the repository are directly added to the tree)
TreeTableNode repRoot; // root of repChange tree
TreeTableNode newCommitNode; // new commit being made
int versioningFormat;
// for caching purposes
URL repHeaderLoc; // actual URL location of repository header annotation
TreeTableNode[] versionNodes; // array of version commit TreeTableNodes
Description[] versionDescriptions; // array of version commit Descriptions
// 0 - rep. header Description, 1..headVersionNum: version Descriptions
// swoop ontology info
OWLOntology swoopOnt, syncOntology;
URI swoopOntURI;
List ontChanges;
JComboBox ontBox;
// UI info
Font tahoma = new Font("Tahoma", Font.PLAIN, 11);
final String[] cNames = {"Author", "Description", "Date", "Entity"};
JTextField swoopOntFld;
JLabel swoopOntLbl;
JRadioButton existingOntRadio, newOntRadio;
JButton refreshBtn, swoUpdateBtn, swoCommitBtn, swoDeleteBtn, swoSelAllBtn, swoTestBtn, swoFilterBtn;
JSplitPane splitPane, ontTablePane, repTablePane;
JCheckBox advancedChk;
boolean advanced = true;
JPanel leftPanel, rightPanel;
JTextField repAuthorFld, repDateFld, repURLFld, repBaseOntFld;
JComboBox repTypeBox;
JTreeTable ontChangeTT, repChangeTT;
JEditorPane ontChangeEdPane, repChangeEdPane;
JButton repUpdateBtn, repCommitBtn, repDeleteBtn, repSelAllBtn, repTestBtn, repFilterBtn;
JButton moveRBtn, moveLBtn;
JPopupMenu swoFilterMenu, repFilterMenu;
JMenuItem swoRedFMenu, swoRepFMenu, swoLocFMenu, repRedFMenu;
public boolean DEBUG = true;
JLabel statusBar;
int splitPaneDivPos;
// cache info
Map nodeMap;
public VersionedOntology(SwoopModel swoopModel, VersionControl controlHandler) {
init(swoopModel, controlHandler);
}
// another constructor which accepts a preloaded versionDescriptions[] array and
// parses it to obtain all saved versioning info
public VersionedOntology(SwoopModel swoopModel, VersionControl controlHandler, URI repURI, Description[] verDesc) {
init(swoopModel, controlHandler);
this.repositoryURI = repURI;
this.versionDescriptions = verDesc;
// parse version Description array
try {
// first parse header
Description header = versionDescriptions[0];
// parse header description to get author, date, baseOntologyURI
this.repositoryAuthor = header.getAuthor();
this.reposityCreatedDate = header.getCreated();
this.baseOntologyURI = new URI(header.getAnnotatedEntityDefinition());
// and headVersionNumber
this.headVersionNumber = Integer.parseInt(header.getBody());
// also get actual URL location of annotation
this.repHeaderLoc = header.getLocation();
// set UI accordingly
this.repURLFld.setText(this.repositoryURI.toString());
this.repAuthorFld.setText(this.repositoryAuthor);
this.repDateFld.setText(this.reposityCreatedDate);
this.repBaseOntFld.setText(this.baseOntologyURI.toString());
this.toggleRepOptions(false);
// now for each version, parse and add node to repRoot
for (int ctr=1; ctr<=this.headVersionNumber; ctr++) {
Description version = versionDescriptions[ctr];
TreeTableNode mainNode = this.parseSingleCommit(version);
// set params on mainNode
mainNode.swoopChange.isOnRepository = true;
mainNode.location = version.getLocation();
versionNodes[ctr] = mainNode;
}
// again set UI accordingly
this.refreshRepTreeTable(true);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/*
* Simple initialization of this class
*/
private void init(SwoopModel swoopModel, VersionControl controlHandler) {
this.swoopModel = swoopModel;
this.swoopModel.addListener(this);
this.controlHandler = controlHandler;
this.versionNodes = new TreeTableNode[99999];
this.versionDescriptions = new Description[99999];
this.nodeMap = new HashMap();
this.setupUI();
this.refreshOntBox();
this.setupFilterPopupMenus();
this.toggleAdvanced(false);
}
/**
* @return Returns the headVersionNumber.
*/
public int getHeadVersionNumber() {
return headVersionNumber;
}
/**
* @param headVersionNumber The headVersionNumber to set.
*/
public void setHeadVersionNumber(int headVersionNumber) {
this.headVersionNumber = headVersionNumber;
}
/**
* @return Returns the repositoryAuthor.
*/
public String getRepositoryAuthor() {
return repositoryAuthor;
}
/**
* @param repositoryAuthor The repositoryAuthor to set.
*/
public void setRepositoryAuthor(String repositoryAuthor) {
this.repositoryAuthor = repositoryAuthor;
}
/**
* @return Returns the repositoryURL.
*/
public URI getRepositoryURL() {
return repositoryURI;
}
/**
* @param repositoryURL The repositoryURL to set.
*/
public void setRepositoryURL(URI repositoryURL) {
this.repositoryURI = repositoryURL;
}
/**
* @return Returns the reposityCreatedDate.
*/
public String getReposityCreatedDate() {
return reposityCreatedDate;
}
/**
* @param reposityCreatedDate The reposityCreatedDate to set.
*/
public void setReposityCreatedDate(String reposityCreatedDate) {
this.reposityCreatedDate = reposityCreatedDate;
}
/**
* @return Returns the versioningFormat.
*/
public int getVersioningFormat() {
return versioningFormat;
}
/**
* @param versioningFormat The versioningFormat to set.
*/
public void setVersioningFormat(int versioningFormat) {
this.versioningFormat = versioningFormat;
}
private void setupUI() {
// setup border
Border border = new EtchedBorder();
// explorer style interface - left: swoop ontology, right: repository ontology
// LEFT PANEL
// setup ontology panel
swoopOntLbl = (JLabel) this.initComponent(JLabel.class, "Specify Swoop Ontology");
swoopOntFld = (JTextField) this.initComponent(JTextField.class, "");
ontBox = new JComboBox();
ontBox.setRenderer(new OntologyListRenderer(swoopModel));
existingOntRadio = (JRadioButton) this.initComponent(JRadioButton.class, "Existing: ");
newOntRadio = (JRadioButton) this.initComponent(JRadioButton.class, "New URI:");
ButtonGroup group = new ButtonGroup();
group.add(existingOntRadio);
group.add(newOntRadio);
existingOntRadio.setSelected(true);
refreshBtn = (JButton) this.initComponent(JButton.class, "Refresh");
JPanel ontSelPanel = this.createPanel(null, ontBox, refreshBtn);
JPanel radio1 = this.createPanel(existingOntRadio, ontSelPanel, null);
JPanel radio2 = this.createPanel(newOntRadio, swoopOntFld, null);
JPanel ontPanel = new JPanel();
ontPanel.setLayout(new GridLayout(5,1));
ontPanel.add(swoopOntLbl);
ontPanel.add(radio1);
ontPanel.add(radio2);
ontPanel.add(new JLabel(""));
ontPanel.add(new JLabel(""));
// create swoop ontology toolbar
swoDeleteBtn = (JButton) this.initComponent(JButton.class, "Delete");
swoSelAllBtn = (JButton) this.initComponent(JButton.class, "Select All");
swoTestBtn = (JButton) this.initComponent(JButton.class, "Test All");
swoFilterBtn = (JButton) this.initComponent(JButton.class, "Filter");
swoFilterBtn.addMouseListener(this);
JToolBar swoToolBar = new JToolBar();
swoToolBar.add(swoSelAllBtn);
swoToolBar.add(swoDeleteBtn);
swoToolBar.add(swoTestBtn);
swoToolBar.add(swoFilterBtn);
// ontPanel.setBorder(border);
// create ont changes panel
JPanel ontChangePanel = new JPanel();
ontChangePanel.setLayout(new BorderLayout());
// initialize change treetable and change editorpane
ontChangeTT = new JTreeTable(new DefaultTreeTableModel(getTreeRoot(), cNames));
ontChangeTT.setFont(tahoma);
ontChangeTT.getTree().setRootVisible(false);
ontChangeTT.getTree().addTreeSelectionListener(this);
ontTablePane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
ontTablePane.setTopComponent(new JScrollPane(ontChangeTT));
ontChangeEdPane = new JEditorPane();
ontChangeEdPane.setContentType("text/html");
ontChangeEdPane.setEditable(false);
ontChangeEdPane.addHyperlinkListener(this);
ontTablePane.setBottomComponent(new JScrollPane(ontChangeEdPane));
ontChanges = new ArrayList();
// initialize button panel
JPanel ontBtnPanel = new JPanel();
ontBtnPanel.setLayout(new GridLayout(1,4));
ontBtnPanel.add(new JLabel(""));
swoUpdateBtn = (JButton) this.initComponent(JButton.class, "Update");
swoCommitBtn = (JButton) this.initComponent(JButton.class, "Commit");
ontBtnPanel.add(swoUpdateBtn);
ontBtnPanel.add(swoCommitBtn);
ontBtnPanel.add(new JLabel(""));
ontChangePanel.add(ontTablePane, "Center");
ontChangePanel.add(ontBtnPanel, "South");
moveRBtn = (JButton) this.initComponent(JButton.class, "");
SwoopIcons swi = new SwoopIcons();
moveRBtn.setIcon(swi.nextIcon);
moveLBtn = (JButton) this.initComponent(JButton.class, "");
moveLBtn.setIcon(swi.prevIcon);
JPanel movePanel = this.createColPanel(moveRBtn, moveLBtn);
ontChangePanel.add(movePanel, "East");
leftPanel = new JPanel();
leftPanel.setLayout(new BorderLayout());
JPanel northPnl = new JPanel();
northPnl.setLayout(new BorderLayout());
northPnl.add(ontPanel, "Center");
northPnl.add(swoToolBar, "South");
leftPanel.add(northPnl, "North");
leftPanel.add(ontChangePanel, "Center");
// RIGHT PANEL
// setup repository info
JPanel repPanel = new JPanel();
JLabel repAuthorLbl = (JLabel) initComponent(JLabel.class, "Repository Author:");
JLabel repDateLbl = (JLabel) initComponent(JLabel.class, "Repository Created Date:");
JLabel repURLLbl = (JLabel) initComponent(JLabel.class, "Repository URL:");
repAuthorFld = (JTextField) initComponent(JTextField.class, "");
repDateFld = (JTextField) initComponent(JTextField.class, "");
repURLFld = (JTextField) initComponent(JTextField.class, "");
repURLFld.addKeyListener(this);
JLabel repBaseOntLbl = (JLabel) initComponent(JLabel.class, "Repository Base Ontology URI:");
repBaseOntFld = (JTextField) initComponent(JTextField.class, "");
repTypeBox = (JComboBox) initComponent(JComboBox.class, "");
repTypeBox.addItem(this.getVersioningType());
repPanel.setLayout(new SpringLayout());
repPanel.add(repURLLbl);
repPanel.add(repURLFld);
repPanel.add(repAuthorLbl);
repPanel.add(repAuthorFld);
repPanel.add(repDateLbl);
repPanel.add(repDateFld);
repPanel.add(repBaseOntLbl);
repPanel.add(repBaseOntFld);
SpringUtilities.makeCompactGrid(repPanel,
4, 2, // rows, cols
6, 6, //initX, initY
6, 6); //xPad, yPad
repPanel.setBorder(border);
// create toolbar panel
JToolBar repToolBar = new JToolBar();
repDeleteBtn = (JButton) this.initComponent(JButton.class, "Delete");
repSelAllBtn = (JButton) this.initComponent(JButton.class, "Select All");
repTestBtn = (JButton) this.initComponent(JButton.class, "Test All");
repFilterBtn = (JButton) this.initComponent(JButton.class, "Filter");
repFilterBtn.addMouseListener(this);
repToolBar.add(repSelAllBtn);
repToolBar.add(repDeleteBtn);
repToolBar.add(repTestBtn);
repToolBar.add(repFilterBtn);
// create changes panel
JPanel repChangePanel = new JPanel();
repChangePanel.setLayout(new BorderLayout());
// initialize change treetable and change editorpane
repRoot = getTreeRoot();
// also initialize newCommitNode
newCommitNode = new TreeTableNode(new SwoopChange(swoopModel.getUserName(), null, null, swoopModel.getTimeStamp(), "New Version Commit", true, true));
newCommitNode.swoopChange.isTopNode = true;
// add newCommitNode to root
repRoot.addChild(newCommitNode);
repChangeTT = new JTreeTable(new DefaultTreeTableModel(repRoot, cNames));
this.repChangeTT.setFont(tahoma);
repChangeTT.getTree().setRootVisible(false);
repChangeTT.getTree().addTreeSelectionListener(this);
repTablePane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
repTablePane.setTopComponent(new JScrollPane(repChangeTT));
repChangeEdPane = new JEditorPane();
repChangeEdPane.setContentType("text/html");
repChangeEdPane.setEditable(false);
repChangeEdPane.addHyperlinkListener(this);
repTablePane.setBottomComponent(new JScrollPane(repChangeEdPane));
repChanges = new ArrayList();
// initialize button panel
JPanel repBtnPanel = new JPanel();
repBtnPanel.setLayout(new GridLayout(1,4));
repBtnPanel.add(new JLabel(""));
repUpdateBtn = (JButton) this.initComponent(JButton.class, "Update");
repCommitBtn = (JButton) this.initComponent(JButton.class, "Commit");
repBtnPanel.add(repUpdateBtn);
repBtnPanel.add(repCommitBtn);
repBtnPanel.add(new JLabel(""));
repChangePanel.add(repTablePane, "Center");
repChangePanel.add(repBtnPanel, "South");
// right panel setup
rightPanel = new JPanel();
rightPanel.setLayout(new BorderLayout());
JPanel northPanel = new JPanel();
northPanel.setLayout(new BorderLayout());
northPanel.add(repPanel, "Center");
northPanel.add(repToolBar, "South");
rightPanel.add(northPanel, "North");
rightPanel.add(repChangePanel, "Center");
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setLeftComponent(leftPanel);
splitPane.setRightComponent(rightPanel);
// main panel setup
setLayout(new BorderLayout());
// create topPanel with advanced check box
JPanel topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
this.advancedChk = (JCheckBox) this.initComponent(JCheckBox.class, "Advanced");
topPanel.add(advancedChk, "East");
add(topPanel, "North");
add(splitPane, "Center");
// add status bar at the south
statusBar = (JLabel) this.initComponent(JLabel.class, "Status:");
statusBar.setFont(new Font("Verdana", Font.BOLD, 10));
add(statusBar, "South");
// set dividers after adding to ui
ontTablePane.setDividerLocation(200);
repTablePane.setDividerLocation(200);
splitPane.setDividerLocation(300);
}
/*
* Create PopupMenus for the Filtering options for each changeTreeTable
*/
private void setupFilterPopupMenus() {
// setup swoop ontology filter menu
this.swoFilterMenu = new JPopupMenu();
this.swoRedFMenu = (JMenuItem) this.initComponent(JMenuItem.class, "Remove Redundant Changes");
this.swoRepFMenu = (JMenuItem) this.initComponent(JMenuItem.class, "Remove Repository Changes");
this.swoLocFMenu = (JMenuItem) this.initComponent(JMenuItem.class, "Remove Local Changes");
this.swoFilterMenu.add(swoRedFMenu);
this.swoFilterMenu.add(swoRepFMenu);
this.swoFilterMenu.add(swoLocFMenu);
// setup repository ontology filter menu
this.repFilterMenu = new JPopupMenu();
this.repRedFMenu = (JMenuItem) this.initComponent(JMenuItem.class, "Remove Redundant Changes");
this.repFilterMenu.add(repRedFMenu);
}
/**
* Common method to initialize JComponents in the UI
*/
private JComponent initComponent(Class compClass, String label) {
JComponent comp = null;
if (compClass == JLabel.class) {
comp = new JLabel(label);
}
else if (compClass == JTextField.class) {
comp = new JTextField();
}
else if (compClass == JComboBox.class) {
comp = new JComboBox();
((JComboBox) comp).addActionListener(this);
}
else if (compClass == JButton.class) {
comp = new JButton(label);
((JButton) comp).addActionListener(this);
}
else if (compClass == JRadioButton.class) {
comp = new JRadioButton(label);
((JRadioButton) comp).addActionListener(this);
}
else if (compClass == JMenuItem.class) {
comp = new JMenuItem(label);
((JMenuItem) comp).addActionListener(this);
}
else if (compClass == JCheckBox.class) {
comp = new JCheckBox(label);
((JCheckBox) comp).addActionListener(this);
}
comp.setFont(tahoma);
return comp;
}
private JPanel createPanel(JComponent left, JComponent center, JComponent right) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
if (left!=null) panel.add(left, "West");
panel.add(center, "Center");
if (right!=null) panel.add(right, "East");
return panel;
}
private String getVersioningType() {
switch (versioningFormat) {
case 0 :
return "Annotated Change Set";
// maybe other types of formats: ontology as a whole etc
}
return "";
}
public TreeTableNode getTreeRoot() {
SwoopChange root = null;
try {
root = new SwoopChange("", new URI("/"), null, "", "", true, true);
}
catch (Exception ex) {
}
return new TreeTableNode(root);
}
public void actionPerformed(ActionEvent e) {
// if ontology box is selected
if (e.getSource()==ontBox && e.getActionCommand().equals("comboBoxChanged")) {
// load changes from Swoop into this pane
}
// if swoop ontology update button is pressed
else if (e.getSource() == swoUpdateBtn) {
this.updateOntChanges();
}
// if swoop ontology commit button is pressed
else if (e.getSource() == swoCommitBtn) {
this.commitOntChanges(false);
}
// if ont -> rep transfer button is pressed
else if (e.getSource() == moveRBtn) {
this.transferChanges(ontChangeTT, repChangeTT);
}
// if rep -> ont transfer button is pressed
else if (e.getSource() == moveLBtn) {
this.transferChanges(repChangeTT, ontChangeTT);
}
// if rep commit button is pressed
else if (e.getSource() == repCommitBtn) {
this.commitRepChanges();
}
// if rep update button is pressed
else if (e.getSource() == repUpdateBtn) {
this.updateRepChanges(true);
}
// if delete swoop ontology annotations button is pressed
else if (e.getSource() == swoDeleteBtn) {
this.deleteChanges(ontChangeTT);
}
// if delete repository annotations button is pressed
else if (e.getSource() == repDeleteBtn) {
this.deleteChanges(repChangeTT);
// this.deleteRepository(); // TESTING PURPOSES ONLY
}
else if (e.getSource() == swoSelAllBtn) {
ontChangeTT.selectAll();
ontChangeTT.selectAll(); // need to do it twice?! Fix this
}
else if (e.getSource() == repSelAllBtn) {
repChangeTT.selectAll();
repChangeTT.selectAll();
}
// swoop ontology: test changes
else if (e.getSource() == swoTestBtn) {
this.testChanges(false);
}
// repository: test changes
else if (e.getSource() == repTestBtn) {
this.testChanges(true);
}
// filter menus
else if (e.getSource() == swoRedFMenu) {
this.filter(false, this.REDUNDANT_CHANGE);
}
else if (e.getSource() == swoRepFMenu) {
this.filter(false, this.REPOSITORY_CHANGE);
}
else if (e.getSource() == swoLocFMenu) {
this.filter(false, this.LOCAL_CHANGE);
}
else if (e.getSource() == repRedFMenu) {
this.filter(true, this.REDUNDANT_CHANGE);
}
// advanced check box
else if (e.getSource() == advancedChk) {
this.toggleAdvanced(advancedChk.isSelected());
}
}
/*
* Toggle the Advanced Check Box UI setting
*/
private void toggleAdvanced(boolean enable) {
this.advanced = enable;
if (enable) {
this.leftPanel.setVisible(true);
splitPane.setDividerLocation(splitPaneDivPos);
// controlHandler.setSize(800, 600);
}
else {
splitPaneDivPos = splitPane.getDividerLocation();
this.leftPanel.setVisible(false);
splitPane.setDividerLocation(0);
// controlHandler.setSize(400, 600);
}
}
/*
* Refresh Ontology Selection Box from SwoopModel
*
*/
protected void refreshOntBox() {
ontBox.removeAllItems();
Set sortedOntSet = new TreeSet(OntologyComparator.INSTANCE);
sortedOntSet.addAll(swoopModel.getOntologies());
for (Iterator iter=sortedOntSet.iterator(); iter.hasNext();) {
OWLOntology ont = (OWLOntology) iter.next();
ontBox.addItem(ont);
}
}
/* Create column panel for transfer buttons */
private JPanel createColPanel(JButton btn1, JButton btn2) {
JPanel colPanel = new JPanel();
colPanel.setLayout(new GridLayout(10,1));
for (int i=0; i<3; i++) colPanel.add(new JLabel(""));
colPanel.add(btn1);
colPanel.add(btn2);
for (int i=0; i<5; i++) colPanel.add(new JLabel(""));
return colPanel;
}
// update changes list from swoop ontology
private void updateOntChanges() {
try {
String status = "Status: [ACTION - Update Local Ontology]...";
statusBar.setText(status);
if (existingOntRadio.isSelected()) {
OWLOntology ont = (OWLOntology) ontBox.getSelectedItem();
List changes = swoopModel.getChangesCache().getChangeList(ont.getURI());
for (int i=0; i<changes.size(); i++) {
SwoopChange swc = (SwoopChange) changes.get(i);
if (!isPresent(ontChanges, swc)) ontChanges.add(swc.clone());
}
this.sortChanges(ontChanges);
this.refreshOntTreeTable();
}
statusBar.setText(status+"DONE");
}
catch (OWLException ex) {
ex.printStackTrace();
}
}
public void refreshOntTreeTable() {
// get rootnode from changetreetable
JTree changeTree = ontChangeTT.getTree();
TreeTableNode rootNode = (TreeTableNode) changeTree.getModel().getRoot();
rootNode.children = new Vector();
this.ontChangeEdPane.setText("");
// populate node tree
for (Iterator changeIter = ontChanges.iterator(); changeIter.hasNext();) {
SwoopChange swc = (SwoopChange) changeIter.next();
// skip checkpoint related changes
if (!swc.isCheckpointRelated /*&& swc.isCommitted*/) {
TreeTableNode changeNode = new TreeTableNode(swc);
rootNode.addChild(changeNode);
}
}
ontChangeTT.getTree().updateUI();
this.refreshUI();
}
private void refreshUI() {
int loc = ontTablePane.getDividerLocation();
ontTablePane.setTopComponent(new JScrollPane(ontChangeTT));
ontTablePane.setDividerLocation(loc);
loc = repTablePane.getDividerLocation();
repTablePane.setTopComponent(new JScrollPane(repChangeTT));
repTablePane.setDividerLocation(loc);
}
/**
* transfer selected changes from Swoop Ont list to Repository List
* or vice versa
*/
public void transferChanges(JTreeTable source, JTreeTable target) {
// add to changes in target based on source
JEditorPane changePane = null;
List changes = null;
boolean refreshOntTT = true;
if (target == ontChangeTT) {
changes = ontChanges;
changePane = ontChangeEdPane;
}
else {
refreshOntTT = false;
changes = repChanges;
changePane= repChangeEdPane;
}
// get selected changes in source
if (source.getTree().getSelectionPath()==null) return;
TreePath[] paths = source.getTree().getSelectionPaths();
for (int i=0; i<paths.length; i++) {
TreePath path = paths[i];
TreeTableNode selNode = (TreeTableNode) path.getLastPathComponent();
if (selNode.swoopChange.isTopNode) {
// skip version top nodes, but transfer its children
for (Iterator iter = selNode.children.iterator(); iter.hasNext();) {
TreeTableNode childNode = (TreeTableNode) iter.next();
SwoopChange swc = (SwoopChange) childNode.swoopChange;
// check if it already exists in changes (prevent duplicates)
if (!isPresent(changes, swc)) changes.add(swc.clone());
}
}
else {
SwoopChange swc = (SwoopChange) selNode.swoopChange;
// check if it already exists in changes (prevent duplicates)
if (!isPresent(changes, swc)) changes.add(swc.clone());
}
}
this.sortChanges(changes);
// refresh UI of target after adding changes
if (refreshOntTT) this.refreshOntTreeTable();
else {
// add (new) repChanges to newCommit node directly
newCommitNode.children = new Vector();
for (Iterator iter = changes.iterator(); iter.hasNext();) {
SwoopChange swc = (SwoopChange) iter.next();
TreeTableNode swcNode = new TreeTableNode(swc);
newCommitNode.addChild(swcNode);
}
this.refreshRepTreeTable(true);
}
}
/*
* Check if a swoopChange is present in the changes list.
* Check if the author, ontologychange and timestamp matches
* since these 3 params determine uniqueness
*/
private boolean isPresent(List changes, SwoopChange check) {
for (Iterator iter = changes.iterator(); iter.hasNext();) {
SwoopChange swc = (SwoopChange) iter.next();
if (swc.getAuthor().equals(check.getAuthor()) &&
swc.getDescription().equals(check.getDescription()) &&
// swc.getChange().equals(check.getChange()) &&
swc.getTimeStamp().equals(check.getTimeStamp()))
return true;
}
return false;
}
/***
* Make a commit to the selected repository
* 1. Check if the repository already exists
* 2. Check if all changes on the repository are in Swoop
* 3. Check that there are no clashes involving changes (testChanges(..))
* 4. Commit new version alone!
*/
private void commitRepChanges() {
// get repository info
String repURL = repURLFld.getText();
String boURI = repBaseOntFld.getText();
this.repositoryAuthor = repAuthorFld.getText();
this.reposityCreatedDate = repDateFld.getText();
String status = "Status: [ACTION - Commit to Repository]...";
try {
this.repositoryURI = new URI(repURL);
this.baseOntologyURI = new URI(boURI);
}
catch (URISyntaxException ex) {
statusBar.setText(status+"Invalid Repository URL and/or Base Ontology URI");
return;
}
try {
// check if repository already exists
boolean repExists = this.loadRepositoryHeader();
if (!repExists) {
// creating new repository
// form repository header
URI[] headerURI = new URI[1];
headerURI[0] = new URI(this.repositoryURI+"#header");
if (this.repositoryAuthor.equals("") || this.reposityCreatedDate.equals("")) {
int opt = JOptionPane.showConfirmDialog(null, "Repository Author and/or Date not specified. Continue?", "Creating Repository", JOptionPane.YES_NO_OPTION);
if (opt == JOptionPane.NO_OPTION) return;
}
// create annotea description for header
Description header = new Description();
header.setAnnotates(headerURI);
header.setAuthor(this.repositoryAuthor);
header.setCreated(this.reposityCreatedDate);
header.setAnnotatedEntityDefinition(this.baseOntologyURI.toString());
this.headVersionNumber = 0;
header.setBody(String.valueOf(this.headVersionNumber));
header.setBodyType("text/html");
header.setAnnotationType(this.annotType);
client.post(header);
statusBar.setText(status+"Ontology Repository Header posted at "+headerURI[0]);
toggleRepOptions(false);
versionDescriptions[0] = header;
swoopModel.updateVersionRepository(repositoryURI, versionDescriptions);
}
// test changes
boolean success = this.testChanges(true);
if (success){
// prompt user for comment on commit
String commitComment = JOptionPane.showInputDialog(this, "COMMIT New Version (Details):");
if (commitComment==null) {
statusBar.setText(status+"CANCELLED");
return;
}
// transform SwoopChange list to Description list (to save author, date, uris etc)
List descList = transformChangeList(repChanges);
// serialize each description into RDF/XML
// and make it one large string with separator ("[SWOOP-ANNOTATED-CHANGE-SET]") in the middle
String largeChangeSetString = "";
for (Iterator iter = descList.iterator(); iter.hasNext();) {
Description desc = (Description) iter.next();
String descStr = desc.serializeIntoString(swoopModel);
largeChangeSetString += descStr + separator;
}
// ENCODE CDATA
largeChangeSetString = largeChangeSetString.replaceAll("CDATA", "ENCODED-CDATA");
largeChangeSetString = largeChangeSetString.replaceAll("]]>", "]ENCODED]>");
// finally commit a single annotation with the entire changeset string in the body
// also allow author to make annotation on commit
Description commit = new Description();
commit.setAuthor(swoopModel.getUserName());
commit.setCreated(swoopModel.getTimeStamp());
commit.setBody(largeChangeSetString);
commit.setBodyType("text/html");
commit.setAnnotatedEntityDefinition(commitComment);
commit.setAnnotationType(this.annotType);
// increment headVersionNum and write new commit
// at repURL+"#"+headVersionNum
this.headVersionNumber++;
URI[] annotates = new URI[1];
annotates[0] = new URI(repositoryURI.toString()+"#"+String.valueOf(this.headVersionNumber));
commit.setAnnotates(annotates);
// COMMIT!
client.post(commit);
// post-process:
// 1. rewrite rep header added newly incremented headVersionNumber
this.rewriteRepHeader();
// 2. set newCommitNode params to current commit
newCommitNode.swoopChange.setAuthor(commit.getAuthor());
newCommitNode.swoopChange.setTimeStamp(commit.getCreated());
newCommitNode.swoopChange.setDescription(commit.getAnnotatedEntityDefinition());
// 3. save newCommitNode in versionCommits array and Description in versionDescriptions array
versionNodes[this.headVersionNumber] = newCommitNode;
versionDescriptions[this.headVersionNumber] = commit;
swoopModel.updateVersionRepository(repositoryURI, versionDescriptions);
// 4. for each child of newCommitNode, set its swoopChange.onRepository value to true
for (Iterator iter3=newCommitNode.children.iterator(); iter3.hasNext();) {
TreeTableNode child = (TreeTableNode) iter3.next();
child.swoopChange.isOnRepository = true;
}
// 5. create newCommitNode and add to root at the end
newCommitNode = new TreeTableNode(new SwoopChange(swoopModel.getUserName(), null, null, swoopModel.getTimeStamp(), "New Version Commit", true, false));
newCommitNode.swoopChange.isTopNode = true;
repRoot.addChild(newCommitNode);
repChanges = new ArrayList(); // also clear this
statusBar.setText(status+"Committed New Version "+this.headVersionNumber);
}
}
catch (Exception ex) {
ex.printStackTrace();
statusBar.setText(status+"FAILED");
}
this.refreshRepTreeTable(false);
}
/*
* Test the changes in the ontChange list or repChange list
* i.e. Take the initial base ontology, apply changes,
* see if clash occurs, and remove all redundant changes (that do not cause change in ontology)
* @return
*/
private boolean testChanges(boolean testRepository) {
if (testRepository) {
String status = "Status: [ACTION - Testing Repository Changes]...";
// test changes in repository for clashes etc.
statusBar.setText(status);
boolean testSuccess = true;
int failCount = 0;
try {
// do an update first to make sure rep-side changes are all there
boolean updateSuccess = this.updateRepChanges(false);
if (!updateSuccess) {
statusBar.setText(status+"Update FAILED");
return false;
}
// load baseOntology using URI
statusBar.setText(status+"Loading Base Ontology");
OWLOntology baseOntology = swoopModel.loadOntology(baseOntologyURI);
if (baseOntology == null) {
// there is no base ontology, changes start from scratch
// create new ontology using OWLBuilder
OWLBuilder builder = new OWLBuilder();
builder.createOntology(baseOntologyURI, baseOntologyURI);
baseOntology = builder.getOntology();
}
// get all repository side changes: under repRoot
List allRepChanges = this.getDescendantChanges(repRoot);
statusBar.setText(status+"Testing "+allRepChanges.size()+" repository-side changes");
// apply allRepChanges to baseOntology
for (int i=0; i<allRepChanges.size(); i++) {
SwoopChange swc = (SwoopChange) allRepChanges.get(i);
OntologyChange oc = swc.getChange();
//*** need to align changes with ontology! ***/
try {
OntologyChange alignOC = (OntologyChange) controlHandler.swoopHandler.changeLog.getChangeInformation(oc, ChangeLog.CHANGE_ALIGN, null, new ArrayList(), baseOntology);
// save state of baseOntology and see if it changes
// use Abstract Syntax since its more concise than rdf/xml?
String before = controlHandler.swoopHandler.changeLog.getOntSnapshot(baseOntology);
// APPLY CHANGE
boolean check = true;
if (alignOC instanceof BooleanElementChange) {
check = swoopModel.applyBooleanElementChange(alignOC);
}
else if (alignOC instanceof EnumElementChange) {
check = swoopModel.applyEnumElementChange(alignOC);
}
else alignOC.accept((ChangeVisitor) baseOntology);
// need to see if any change in the ontology occured
String after = controlHandler.swoopHandler.changeLog.getOntSnapshot(baseOntology);
if (before.equals(after) || !check) {
// nothing has changed!
System.out.println("Found redundant change: "+oc);
swc.isRedundant = true;
testSuccess = false;
failCount++;
}
else swc.isRedundant = false;
}
catch (Exception ex) {
swc.isRedundant = true;
System.out.println("Change Error for: "+oc);
testSuccess = false;
failCount++;
ex.printStackTrace();
}
}
}
catch (Exception ex) {
ex.printStackTrace();
testSuccess = false;
}
if (testSuccess) statusBar.setText(status+"Test PASSED");
else {
statusBar.setText(status+"Test FAILED");
JOptionPane.showMessageDialog(this, "Change Test FAILED: "+failCount+" change(s) is/are redundant or cause clashes. Please Fix/Remove them and try again.");
}
// refresh repTreeTable
this.refreshRepTreeTable(false);
return testSuccess;
}
else {
// test changes in Swoop Ontology for clashes etc.
String status = "Status: [ACTION - Testing LOCAL Ontology Changes]...";
statusBar.setText(status);
boolean testSuccess = true;
int failCount = 0;
// get base ontology
statusBar.setText(status+"Loading Base Ontology");
OWLOntology baseOntology = null;
if (existingOntRadio.isSelected()) {
// get existing ontology from swoopModel
baseOntology = (OWLOntology) ontBox.getSelectedItem();
// but clone it to prevent applying changes on *it*
baseOntology = this.cloneOntology(baseOntology);
}
else {
URI ontURI = null;
try {
// load ontology with URI
ontURI = new URI(swoopOntFld.getText());
baseOntology = swoopModel.loadOntology(ontURI);
}
catch (Exception ex) {
// create new ontology
OWLBuilder builder = new OWLBuilder();
try {
builder.createOntology(ontURI, ontURI);
} catch (OWLException e) {
e.printStackTrace();
}
baseOntology = builder.getOntology();
}
}
if (baseOntology == null) {
statusBar.setText(status+"Unable to load base ontology");
return false;
}
try {
for (int i=0; i<ontChanges.size(); i++) {
SwoopChange swc = (SwoopChange) ontChanges.get(i);
OntologyChange oc = swc.getChange();
//*** need to align changes with ontology! ***/
try {
OntologyChange alignOC = (OntologyChange) controlHandler.swoopHandler.changeLog.getChangeInformation(oc, ChangeLog.CHANGE_ALIGN, null, new ArrayList(), baseOntology);
// save state of baseOntology and see if it changes
// use Abstract Syntax since its more concise than rdf/xml?
String before = controlHandler.swoopHandler.changeLog.getOntSnapshot(baseOntology);
// APPLY CHANGE
boolean check = true;
if (alignOC instanceof BooleanElementChange) {
check = swoopModel.applyBooleanElementChange(alignOC);
}
else if (alignOC instanceof EnumElementChange) {
check = swoopModel.applyEnumElementChange(alignOC);
}
else alignOC.accept((ChangeVisitor) baseOntology);
// need to see if any change in the ontology occured
String after = controlHandler.swoopHandler.changeLog.getOntSnapshot(baseOntology);
if (before.equals(after) || !check) {
// nothing has changed!
System.out.println("Found redundant change: "+oc);
swc.isRedundant = true;
testSuccess = false;
failCount++;
}
else swc.isRedundant = false;
}
catch (Exception ex) {
swc.isRedundant = true;
System.out.println("Change Error for: "+oc);
testSuccess = false;
failCount++;
ex.printStackTrace();
}
}
}
catch (Exception ex) {
ex.printStackTrace();
testSuccess = false;
}
if (testSuccess) statusBar.setText(status+"Test PASSED");
else {
statusBar.setText(status+"Test FAILED");
JOptionPane.showMessageDialog(this, "Change Test FAILED: "+failCount+" change(s) is/are redundant or cause clashes. Please Fix/Remove them and try again.");
}
// refresh ontTreeTable
this.refreshOntTreeTable();
return testSuccess;
}
}
/*
* Perform an update on the Repository. This is the only place
* in the code which updates versions from the repository
* and saves them in the local data structure versionCommits
*/
private boolean updateRepChanges(boolean sync) {
try {
// get repository header since we need count of versions
// i.e. headVersionNum
String status = "Status: [ACTION - Update Repository]...";
statusBar.setText(status+"Loading repository header to find headVersionNumber");
boolean existsRep = this.loadRepositoryHeader();
if (!existsRep) {
if (DEBUG) System.out.println("NOT FOUND");
// update from local Swoop log anyway if uri matches ontURI
this.updateRepFromLog(new URI(this.repBaseOntFld.getText()));
return false;
}
statusBar.setText(status+"HeadVersionNum="+this.headVersionNumber);
// note: all version commits have been made to URLs:
// repositoryURL+"#1"..."#headVersionNum"
// so iterate through versionCommits and see if value is null, implying it hasn't been updated
for (int ctr=1; ctr<=this.headVersionNumber; ctr++) {
if (versionNodes[ctr]==null) {
// form URI using ctr
URI versionURI = new URI(this.repositoryURI+"#"+ctr);
statusBar.setText(status+"Updating version at "+versionURI);
Set commitSet = client.findAnnotations(versionURI);
// get single Description (version) at URI
Description version = (Description) commitSet.iterator().next();
versionDescriptions[ctr] = version;
TreeTableNode mainNode = this.parseSingleCommit(version);
// set params on mainNode
mainNode.swoopChange.isOnRepository = true;
mainNode.location = version.getLocation();
versionNodes[ctr] = mainNode;
}
}
// also if advanced is off, update from local copy as well
// if (!advanced) {
// this.updateRepFromLog(new URI(this.repBaseOntFld.getText()));
// }
// resort all nodes under root
this.refreshRepTreeTable(true);
// update version repository cache
swoopModel.updateVersionRepository(repositoryURI, versionDescriptions);
// if sync is true, commit all changes to the synchronized ontology
if (sync) {
statusBar.setText(status+"Synching with Local Swoop Ontology");
this.commitOntChanges(true);
}
statusBar.setText(status+"DONE");
return true;
}
catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
/*
* Parse a single 'Commit' Description to obtain the main top node
* and all the SwoopChange nodes included in that commit
* (put them as children of the main node)
*/
private TreeTableNode parseSingleCommit(Description commit) throws OWLException {
// make the main annotation the top header
SwoopChange main = new SwoopChange();
main.setAuthor(commit.getAuthor());
main.setCommitted(true); // not needed really
main.isTopNode = true; /* this is key */
main.setTimeStamp(commit.getCreated());
main.setDescription(commit.getAnnotatedEntityDefinition());
TreeTableNode mainNode = new TreeTableNode(main);
// parse change set associated with single commit
String changeSetString = commit.getBody();
if (changeSetString!=null) {
// decode CDATA stuff
changeSetString = changeSetString.replaceAll("ENCODED-CDATA", "CDATA");
changeSetString = changeSetString.replaceAll("]ENCODED]>", "]]>");
// now split based on separator
String[] changeStr = changeSetString.split(separator);
// each split component is a separate change
List repDesc = new ArrayList(); // list of Description (changes)
for (int i=0; i<changeStr.length; i++) {
String swcDesc = changeStr[i]; // SwoopChange mapped to a Description serialized in RDF/XML
Description desc = new Description();
desc.deserializeFromString(swcDesc, swoopModel);
repDesc.add(desc);
}
// transform Description list to SwoopChange list
List swcChangeList = this.transformChangeList(repDesc);
// add each swoopChange as a child of mainNode
this.sortChanges(swcChangeList);
for (Iterator iter2 = swcChangeList.iterator(); iter2.hasNext();) {
SwoopChange swc = (SwoopChange) iter2.next();
TreeTableNode swcNode = new TreeTableNode(swc);
swcNode.swoopChange.isOnRepository = true;
mainNode.addChild(swcNode);
}
}
return mainNode;
}
/*
* Load repository header annotation
* and parse annotation to obtain repository information such as
* author, date, baseOntologyURI, and no of version commits
*/
private boolean loadRepositoryHeader() {
try {
// annotation with URI: repositoryURL + "#header"
repositoryURI = new URI(repURLFld.getText());
URI repHeaderURI = new URI(repositoryURI+"#header");
if (client==null) this.initAnnoteaClient();
// get annotation using Annotea
Set headerSet = client.findAnnotations(repHeaderURI);
if (headerSet.size()>0) {
Description header = (Description) headerSet.iterator().next();
versionDescriptions[0] = header;
// parse header description to get author, date, baseOntologyURI
this.repositoryAuthor = header.getAuthor();
this.reposityCreatedDate = header.getCreated();
this.baseOntologyURI = new URI(header.getAnnotatedEntityDefinition());
// and headVersionNumber
this.headVersionNumber = Integer.parseInt(header.getBody());
// also get actual URL location of annotation
this.repHeaderLoc = header.getLocation();
// set UI accordingly
this.repAuthorFld.setText(this.repositoryAuthor);
this.repDateFld.setText(this.reposityCreatedDate);
this.repBaseOntFld.setText(this.baseOntologyURI.toString());
this.toggleRepOptions(false);
System.out.println("Ontology Repository header exists at "+repHeaderURI);
return true;
}
}
catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
/*
* Transform a list of changes from SwoopChange -> Description objects
* or vice versa
*/
private List transformChangeList(List source) {
List target = new ArrayList();
for (int i=0; i<source.size(); i++) {
Object change = source.get(i);
if (change instanceof SwoopChange) {
SwoopChange swc = (SwoopChange) change;
// change SwoopChange to a Description object
Description desc = new Description();
desc.setAuthor(swc.getAuthor());
desc.setCreated(swc.getTimeStamp());
desc.setBody(swc.getDescription());
desc.setBodyType("text/html");
desc.setAnnotatedEntityDefinition(swc.comment);
// create annotates URI from
// 1. repository URL
// 2. owlObjectURI
// 3. extra URIs
URI[] uris = new URI[2+swc.getExtraSubjects().size()];
uris[0] = repositoryURI;
uris[1] = swc.getOwlObjectURI();
for (int j=0; j<swc.getExtraSubjects().size(); j++) {
uris[j+2] = (URI) swc.getExtraSubjects().get(j);
}
desc.setAnnotates(uris);
// attach single ontology change to description
List chngList = new ArrayList();
chngList.add(swc.getChange());
desc.setOntologyChangeSet(chngList);
target.add(desc);
}
else if (change instanceof Description) {
Description desc = (Description) change;
// change Description to SwoopChange object
SwoopChange swc = new SwoopChange();
swc.setAuthor(desc.getAuthor());
swc.setTimeStamp(desc.getCreated());
swc.setDescription(desc.getBody());
swc.comment = desc.getAnnotatedEntityDefinition();
swc.setCommitted(true); // set committed
// get URIs from desc for swc
URI[] uris = desc.getAnnotates();
swc.setOwlObjectURI(uris[1]);
List extraSubjects = new ArrayList();
for (int j=2; j<uris.length; j++) {
extraSubjects.add(uris[j]);
}
swc.setExtraSubjects(extraSubjects);
// get single ontology change object
List chngList = desc.getOntologyChangeSet();
swc.setChange((OntologyChange) chngList.iterator().next());
target.add(swc);
}
}
return target;
}
/*
* Toggle UI enable/disable of Repository Information fields
*/
private void toggleRepOptions(boolean enable) {
Color color = Color.WHITE;
if (!enable) color = Color.LIGHT_GRAY;
this.repAuthorFld.setBackground(color);
this.repBaseOntFld.setBackground(color);
this.repDateFld.setBackground(color);
this.repAuthorFld.setEditable(enable);
this.repBaseOntFld.setEditable(enable);
this.repDateFld.setEditable(enable);
}
public void keyTyped(KeyEvent e) {
if (e.getSource() == repURLFld) this.toggleRepOptions(true);
}
public void keyPressed(KeyEvent arg0) {
}
public void keyReleased(KeyEvent arg0) {
}
private void initAnnoteaClient() {
if (Annotea.INSTANCE==null) Annotea.initializeAnnotea();
try {
client = new AnnoteaClient(new URL(serverURL), swoopModel);
// also set annotType for all Description objects created here
// to the Change type in Annotea
Set annotTypes = Annotea.annotationTypes;
for (Iterator iter = annotTypes.iterator(); iter.hasNext();) {
OWLClass type = (OWLClass) iter.next();
if (type.getURI().toString().toLowerCase().indexOf("change")>=0) {
this.annotType = type;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
/*
* Used only for TESTING Purposes. Delete contents of repository
*/
private void deleteRepository() {
try {
int opt = JOptionPane.showConfirmDialog(this, "Delete entire Repository (all change sets) at "+ repURLFld.getText()+" ?", "Delete All", JOptionPane.YES_NO_OPTION);
if (opt == JOptionPane.NO_OPTION) return;
// delete repository header
if (repHeaderLoc!=null) {
client.delete(this.repHeaderLoc);
System.out.println("Deleted Repository Header at " + repHeaderLoc);
}
else System.out.println("URL location of Repository Header not known");
// delete all commits at Version Controlled Repository
for (int ctr=1; ctr<=this.headVersionNumber; ctr++) {
URL loc = null;
if (versionNodes[ctr]!=null) {
loc = versionNodes[ctr].location;
}
else {
URI versionURI = new URI(this.repositoryURI.toString()+"#"+String.valueOf(ctr));
Set versionSet = client.findAnnotations(versionURI);
loc = ((Description) versionSet.iterator().next()).getLocation();
}
client.delete(loc);
System.out.println("Deleted Version at "+loc);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/*
* Sort all changes in a changeList based on timestamp
*/
private void sortChanges(List changeList) {
SortedSet changeSet = new TreeSet(ChangeComparator.INSTANCE);
changeSet.addAll(changeList);
changeList.clear();
for (Iterator iter = changeSet.iterator(); iter.hasNext();) {
changeList.add(iter.next());
}
}
/*
* Refresh all topNodes (version commits) under (children of) repRoot *
*/
private void refreshRepTreeTable(boolean refreshRoot) {
if (refreshRoot) {
repRoot.children = new Vector();
for (int ctr=1; ctr<=this.headVersionNumber; ctr++) {
repRoot.addChild(this.versionNodes[ctr]);
}
// add new commit node at the end
repRoot.addChild(newCommitNode);
}
// expand the newCommit node
JTree changeTree = repChangeTT.getTree();
int rows = changeTree.getRowCount();
changeTree.expandRow(rows-1);
changeTree.updateUI();
// need to refresh UI
this.refreshUI();
// also set repChanges to equal all changes beneath newCommitNode
this.repChanges = this.getDescendantChanges(newCommitNode);
}
/*
* Delete selected changes from a given TreeTable
*/
private void deleteChanges(JTreeTable source) {
List changes = null;
boolean selectedOntChangeTT = true;
if (source == ontChangeTT) {
changes = new ArrayList(ontChanges);
}
else {
selectedOntChangeTT = false;
changes = new ArrayList(repChanges);
}
// get selected changes in source
if (source.getTree().getSelectionPath()==null) return;
TreePath[] paths = source.getTree().getSelectionPaths();
for (int i=0; i<paths.length; i++) {
TreePath path = paths[i];
TreeTableNode selNode = (TreeTableNode) path.getLastPathComponent();
SwoopChange swc = selNode.swoopChange;
changes.remove(swc);
}
// refresh UI of source after removing changes
if (selectedOntChangeTT) this.refreshOntTreeTable();
else {
// add (new) repChanges to newCommit node directly
newCommitNode.children = new Vector();
for (Iterator iter = changes.iterator(); iter.hasNext();) {
SwoopChange swc = (SwoopChange) iter.next();
TreeTableNode swcNode = new TreeTableNode(swc);
newCommitNode.addChild(swcNode);
}
this.refreshRepTreeTable(false);
}
}
/*
* Recursive method to find all descendant SwoopChanges of a particular TreeTableNode
*/
private List getDescendantChanges(TreeTableNode node) {
List changes = new ArrayList();
// start with node and recurse over children
// dont add the top node which has children
if (node.children.size()>0) {
for (Iterator iter = node.children.iterator(); iter.hasNext();) {
TreeTableNode child = (TreeTableNode) iter.next();
changes.addAll(getDescendantChanges(child));
}
}
else if (!node.swoopChange.isTopNode) changes.add(node.swoopChange);
return changes;
}
/*
* Rewrite Repository Header..
*/
private void rewriteRepHeader() {
// assume that the value of headVersionNum has been
// incremented before coming here
try {
// 1. delete current header
if (client==null) this.initAnnoteaClient();
client.delete(this.repHeaderLoc);
// 2. post new header
Description header = new Description();
URI[] headerURI = new URI[1];
headerURI[0] = new URI(this.repositoryURI.toString() + "#header");
header.setAnnotates(headerURI);
header.setAuthor(this.repositoryAuthor);
header.setCreated(this.reposityCreatedDate);
header.setAnnotatedEntityDefinition(this.baseOntologyURI.toString());
header.setBody(String.valueOf(this.headVersionNumber));
header.setBodyType("text/html");
header.setAnnotationType(this.annotType);
// 3. update new header location URL
repHeaderLoc = client.post(header);
// 4. update value in versionDescriptions array and update swoopModel' versionRepository
this.versionDescriptions[0] = header;
swoopModel.updateVersionRepository(this.repositoryURI, versionDescriptions);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/*
* Commit Changes to the Swoop Ontology (LOCALLY)
*/
private void commitOntChanges(boolean sync) {
String status = "Status: [ACTION - Commit to Local Ontology]...";
// load base ontology first
OWLOntology baseOntology = null;
if (!sync) {
if (existingOntRadio.isSelected()) {
// get existing ontology from swoopModel
baseOntology = (OWLOntology) ontBox.getSelectedItem();
try {
baseOntology = swoopModel.getOntology(baseOntology.getURI());
} catch (OWLException e) {
e.printStackTrace();
}
}
else {
URI ontURI = null;
try {
// load ontology with URI
ontURI = new URI(swoopOntFld.getText());
baseOntology = swoopModel.loadOntology(ontURI);
}
catch (Exception ex) {
// create new ontology
OWLBuilder builder = new OWLBuilder();
try {
builder.createOntology(ontURI, ontURI);
} catch (OWLException e) {
e.printStackTrace();
}
baseOntology = builder.getOntology();
}
try {
//*** remember to add new baseOntology (not currently in SwoopModel) to the model
swoopModel.addOntology(baseOntology);
} catch (OWLException e) {
e.printStackTrace();
}
}
}
else {
// if sync ontology is specified (i.e. not advanced mode)
if (syncOntology == null) {
try {
URI ontURI = new URI(this.repBaseOntFld.getText());
// check if ontology is already in Swoop
if (swoopModel.getOntology(ontURI)!=null) {
//TODO: currently commit changes to present ontology
syncOntology = swoopModel.getOntology(ontURI);
}
else {
// add new ontology to swoop
syncOntology = swoopModel.loadOntology(ontURI);
swoopModel.addOntology(syncOntology);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
baseOntology = syncOntology;
}
if (baseOntology == null) {
statusBar.setText(status+"Unable to load base ontology");
return;
}
// test changes
boolean success = true;
List commitChanges = null;
if (!sync) {
// if sync is not set, i.e. advanced mode is enabled
// commit only ontside changes
commitChanges = ontChanges;
success = this.testChanges(false);
}
else {
// if sync is set, commit all repository-side changes
commitChanges = new ArrayList(this.getDescendantChanges(repRoot));
// need to test any repChanges to check for changes already applied to ontology
try {
List alreadyOntChanges = swoopModel.getChangesCache().getChangeList(syncOntology.getURI());
for (Iterator iter = new ArrayList(commitChanges).iterator(); iter.hasNext();) {
SwoopChange swc = (SwoopChange) iter.next();
if (this.isPresent(alreadyOntChanges, swc)) commitChanges.remove(swc);
}
}
catch (OWLException e) {
e.printStackTrace();
}
}
if (success){
try {
// commit all changes in commitChanges List
for (int i=0; i<commitChanges.size(); i++) {
SwoopChange swc = (SwoopChange) commitChanges.get(i);
if (sync && !swc.isOnRepository) continue; //*** dont commit anything but repository changes to synched ontology
OntologyChange oc = swc.getChange();
//*** need to align changes with base ontology! ***/
OntologyChange alignOC = (OntologyChange) controlHandler.swoopHandler.changeLog.getChangeInformation(oc, ChangeLog.CHANGE_ALIGN, null, new ArrayList(), baseOntology);
// APPLY CHANGE
if (alignOC instanceof BooleanElementChange) {
swoopModel.applyBooleanElementChange(alignOC);
}
else if (alignOC instanceof EnumElementChange) {
swoopModel.applyEnumElementChange(alignOC);
}
else alignOC.accept((ChangeVisitor) baseOntology);
// update changesCache in swoopModel
// first reset aligned ontology change in swc
swc.setChange(alignOC);
// and add *clones* to changesCache in SwoopModel
swoopModel.getChangesCache().addChange(swc.owlObjectURI, (SwoopChange) swc.clone());
// do the same for entities referred to by swc.ontologyChange
// & also add changed entity URI to swoopModel dirty set
OWLEntity entity = swoopModel.getEntity(baseOntology, swc.owlObjectURI, true);
if (swc.getOwlObjectURI().equals(baseOntology.getURI()) && swc.extraSubjects!=null) {
for (Iterator iter = swc.extraSubjects.iterator(); iter.hasNext();) {
URI entityURI = (URI) iter.next();
// add to cache
swoopModel.getChangesCache().addChange(entityURI, (SwoopChange) swc.clone());
// add to dirty set
entity = swoopModel.getEntity(baseOntology, entityURI, true);
}
}
}
//* notify swoopModel!
Set changedOntologies = new HashSet();
changedOntologies.add(baseOntology);
swoopModel.notifyListeners(new ModelChangeEvent(swoopModel, ModelChangeEvent.ONTOLOGY_CHANGED, changedOntologies));
statusBar.setText(status+"Committed "+commitChanges.size()+" changes");
}
catch (OWLException ex) {
ex.printStackTrace();
}
}
}
public void valueChanged(TreeSelectionEvent e) {
if (e.getSource() instanceof JTree) {
// get tree whose selection has changed
JTree source = (JTree) e.getSource();
if (source.getSelectionPath()==null) return;
TreePath path = source.getSelectionPath();
// get selected tree(table) node
TreeTableNode selNode = (TreeTableNode) path.getLastPathComponent();
// display change information based on selected node
this.displayChange(source, selNode);
}
}
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
if (e.getSource() == ontChangeEdPane || e.getSource() == repChangeEdPane) {
String hLink = e.getDescription();
// edit comment of a swoopchange (in a treetablenode)
if (hLink.startsWith("EDIT")) {
String hashCode = hLink.substring(hLink.indexOf(":")+1, hLink.length());
TreeTableNode node = (TreeTableNode) nodeMap.get(hashCode);
String comment = node.swoopChange.comment;
// prompt for new comment
String newComment = (String) JOptionPane.showInputDialog(this, "Specify New Comment", "Comment on Change", JOptionPane.INFORMATION_MESSAGE, null, null, comment);
if (newComment!=null) node.swoopChange.comment = newComment;
String sourceStr = hLink.substring(4, hLink.indexOf(":"));
// depending on local/remote change, refresh display
if (sourceStr.equals("LOCAL")) this.displayChange(ontChangeTT.getTree(), node);
else this.displayChange(repChangeTT.getTree(), node);
}
}
}
}
private void displayChange(JTree source, TreeTableNode node) {
// create HTML description of selected TreeTableNode
// (based on its SwoopChange value)
SwoopChange swc = node.swoopChange;
String html = "<FONT FACE=\""+swoopModel.getFontFace()+"\" SIZE="+swoopModel.getFontSize()+">";
html += "<b>Author</b>: "+swc.getAuthor()+"<br>";
html += "<b>Time</b>: "+swc.getTimeStamp()+"<br>";
html += "<b>Comment</b>: "+swc.comment;
// add 'Edit' Comment link
if (!swc.isOnRepository && !swc.isTopNode) {
String sourceStr = "LOCAL";
if (source == repChangeTT.getTree()) sourceStr = "REMOTE";
html += " <font color=\"green\"><a href=\"EDIT"+sourceStr+":"+node.hashCode()+"\">Edit</a></font>";
nodeMap.put(String.valueOf(node.hashCode()), node);
}
html += "<br><br>";
html += swc.getDescription();
html += "</FONT>";
if (source == ontChangeTT.getTree()) {
this.ontChangeEdPane.setText(html);
}
else if (source == repChangeTT.getTree()) {
this.repChangeEdPane.setText(html);
}
}
/*
* Clone an OWL Ontology by serializing it into RDF/XML
* and deserializing it!
*/
public OWLOntology cloneOntology(OWLOntology source) {
OWLOntology copy = null;
try {
CorrectedRDFRenderer rdfRend = new CorrectedRDFRenderer();
StringWriter st = new StringWriter();
rdfRend.renderOntology(source, st);
copy = swoopModel.loadOntologyInRDF(new StringReader(st.toString()), source.getURI(), true);
}
catch (OWLException ex) {
ex.printStackTrace();
}
return copy;
}
public void mouseClicked(MouseEvent arg0) {
}
public void mousePressed(MouseEvent evt) {
if (evt.getSource() == swoFilterBtn) {
this.swoFilterMenu.show(evt.getComponent(), evt.getX(), evt.getY());
}
else if (evt.getSource() == repFilterBtn) {
this.repFilterMenu.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
public void mouseReleased(MouseEvent evt) {
if (evt.getSource() == swoFilterBtn) {
this.swoFilterMenu.show(evt.getComponent(), evt.getX(), evt.getY());
}
else if (evt.getSource() == repFilterBtn) {
this.repFilterMenu.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
/*
* Filter out all nodes from the corresponding changeTreeTable (swo or rep)
* depending on boolean and type passed to it.
* type is one of REDUNDANT_CHANGE, REPOSITORY_CHANGE, LOCAL_CHANGE
*/
public void filter(boolean onRepository, int type) {
List changes = null;
if (!onRepository) {
// filter from ontChangeTT
changes = this.ontChanges;
}
else {
// filter from repChangeTT
changes = this.repChanges;
}
// iterate through changes and remove any that match type
for (Iterator iter = new ArrayList(changes).iterator(); iter.hasNext();) {
SwoopChange swc = (SwoopChange) iter.next();
if (swc.isRedundant && type==this.REDUNDANT_CHANGE) changes.remove(swc);
else if (swc.isOnRepository && type==this.REPOSITORY_CHANGE) changes.remove(swc);
else if (!swc.isOnRepository && type==this.LOCAL_CHANGE) changes.remove(swc);
}
// sort changes??
// refresh UI of target after adding changes
if (!onRepository) this.refreshOntTreeTable();
else {
// add (new) repChanges to newCommit node directly
newCommitNode.children = new Vector();
for (Iterator iter = changes.iterator(); iter.hasNext();) {
SwoopChange swc = (SwoopChange) iter.next();
TreeTableNode swcNode = new TreeTableNode(swc);
newCommitNode.addChild(swcNode);
}
this.refreshRepTreeTable(true);
}
}
/*
* Update repository treetable
* based on changes made in Swoop for ontology
* with PHYSICAL uri - ontURI
*/
private void updateRepFromLog(URI phyOntURI) {
// first get ontology whose physical uri matches
URI logOntURI = null;
for (Iterator iter = swoopModel.getOntologies().iterator(); iter.hasNext();) {
OWLOntology ont = (OWLOntology) iter.next();
try {
if (ont.getPhysicalURI().equals(phyOntURI)) {
logOntURI = ont.getLogicalURI();
}
}
catch (OWLException ex) {
ex.printStackTrace();
}
}
if (logOntURI==null) {
System.out.println("No Ontology in Swoop has physical URI: "+phyOntURI);
return;
}
// get changes from swoopModel.changeCache
List changes = swoopModel.getChangesCache().getChangeList(logOntURI);
List allRepChanges = this.getDescendantChanges(repRoot);
allRepChanges.removeAll(this.getDescendantChanges(newCommitNode));
for (Iterator iter = new ArrayList(changes).iterator(); iter.hasNext();) {
SwoopChange swc = (SwoopChange) iter.next();
if (this.isPresent(allRepChanges, swc)) changes.remove(swc);
}
this.sortChanges(changes);
// add (new) repChanges to newCommit node directly
newCommitNode.children = new Vector();
for (Iterator iter = changes.iterator(); iter.hasNext();) {
SwoopChange swc = (SwoopChange) iter.next();
TreeTableNode swcNode = new TreeTableNode(swc);
newCommitNode.addChild(swcNode);
}
this.refreshRepTreeTable(true);
}
public void modelChanged(ModelChangeEvent event) {
if (event.getType() == ModelChangeEvent.ONTOLOGY_CHANGED) {
if (!advanced && baseOntologyURI!=null) {// && syncOntology!=null) {
try {
this.updateRepFromLog(new URI(this.repBaseOntFld.getText()));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
}