//The MIT License // // Copyright (c) 2004 Mindswap Research Group, University of Maryland, College Park // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. package org.mindswap.swoop.annotea; import java.awt.BorderLayout; import java.awt.Container; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JToolBar; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import org.mindswap.swoop.SwoopFrame; import org.mindswap.swoop.SwoopModel; import org.mindswap.swoop.change.ChangeLog; import org.mindswap.swoop.utils.SwoopLoader; import org.mindswap.swoop.utils.change.RevertCheckpointChange; import org.mindswap.swoop.utils.change.SaveCheckpointChange; import org.semanticweb.owl.model.OWLEntity; import org.semanticweb.owl.model.OWLNamedObject; import org.semanticweb.owl.model.OWLOntology; import org.semanticweb.owl.model.change.ChangeVisitor; import org.semanticweb.owl.model.change.OntologyChange; /** * @author Aditya Kalyanpur * */ public class AnnoteaAttachment extends JDialog implements ActionListener, HyperlinkListener { List changeSet, renderedChangeSet, selectedChangeSet; // set of ontology change objects List originalAttachment; ChangeLog changeLog; // handler to ChangeLog.java that contains useful methods // JEditorPane attachPane; // main html pane that renders attachment (change set) data JToolBar toolbar; JButton applyChangesBtn, attachBtn, cancelBtn; //Font tahoma = new Font("Tahoma", Font.PLAIN, 11); Font tahoma = new Font("SansSerif", Font.PLAIN, 11); final static int MY_ATTACHMENT = 1; final static int ANNOTATION_ATTACHMENT = 2; int attachScope; int attachType; JRadioButton entityScope, ontScope, wkspcScope; JPanel scopePanel; AnnoteaRenderer annoteaRend; JCheckBox[] checks; List alreadyAttached; public AnnoteaAttachment(ChangeLog changeLog, List changeSet, int attachType, List alreadyAttached) { this.changeLog = changeLog; if (alreadyAttached == null) alreadyAttached = new ArrayList(); this.alreadyAttached = alreadyAttached; setupUI(); OWLNamedObject owlObj = changeLog.swoopModel.getSelectedObject(); initialize(changeSet, owlObj, attachType); renderChangeSet(); } private void setupUI() { Container content = this.getContentPane(); content.setLayout(new BorderLayout()); entityScope = createRadioButton("Entity", ""); ontScope = createRadioButton("Ontology", ""); wkspcScope = createRadioButton("Workspace", ""); ButtonGroup group = new ButtonGroup(); group.add(entityScope); group.add(ontScope); group.add(wkspcScope); scopePanel = new JPanel(); JLabel scopeLbl = new JLabel("Ontology Change Scope:"); scopeLbl.setFont(tahoma); scopePanel.add(scopeLbl); scopePanel.add(entityScope); scopePanel.add(ontScope); scopePanel.add(wkspcScope); content.add(scopePanel, "North"); toolbar = new JToolBar(); applyChangesBtn = createButton("Apply Change Set", "Apply Changes to current Ontology"); attachBtn = createButton("Attach Change Set", "Attach Changes to current Annotea Annotation"); cancelBtn = createButton("Cancel", "Cancel Attachment"); content.add(toolbar, "South"); setTitle("Change Set in Annotation Attachment"); setSize(400, 500); setLocation(200, 200); setModal(true); //setResizable(false); } private JRadioButton createRadioButton(String lbl, String tooltip) { JRadioButton btn = new JRadioButton(lbl); btn.setFont(tahoma); btn.addActionListener(this); btn.setToolTipText(tooltip); return btn; } private JButton createButton(String lbl, String tooltip) { JButton btn = new JButton(lbl); btn.setFont(tahoma); btn.addActionListener(this); btn.setToolTipText(tooltip); toolbar.add(btn); return btn; } /** * Setup Annotea Attachment: parameters and UI * Do this before calling renderChangeSet() * @param changeSet - ontology change set in annotea attachment * @param owlObj - used to determine scope of ontology changes * @param attachType - 2 types (send/receive) */ public void initialize(List changeSet, OWLNamedObject owlObj, int attachType) { // change set initialization this.changeSet = new ArrayList(changeSet); // modify UI and set attachScope depending on attachType this.attachType = attachType; switch (attachType) { case MY_ATTACHMENT : applyChangesBtn.setVisible(false); attachBtn.setVisible(true); scopePanel.setVisible(true); // determine scope from owl-object if (owlObj!=null) { if (owlObj instanceof OWLOntology) { this.attachScope = ChangeLog.ONTOLOGY_SCOPE; ontScope.setSelected(true); } else if (owlObj instanceof OWLEntity) { this.attachScope = ChangeLog.ENTITY_SCOPE; entityScope.setSelected(true); } } else { this.attachScope = changeLog.WORKSPACE_SCOPE; wkspcScope.setSelected(true); } break; case ANNOTATION_ATTACHMENT : attachBtn.setVisible(false); applyChangesBtn.setVisible(true); scopePanel.setVisible(false); attachScope = changeLog.WORKSPACE_SCOPE; originalAttachment = new ArrayList(changeSet); break; } } /** * Render current Change Set in Annotea Attachment * as HTML in the JEditor Pane * */ public void renderChangeSet() { int saveScope = changeLog.scope; //IMPORTANT changeLog.scope = attachScope; // if (attachType==MY_ATTACHMENT) changeHTML += "<u>Current Committed Changes:</u><br><br>"; // else changeHTML += "<u>Changes in Annotation Message:</u><br><br>"; JEditorPane[] changePanes = new JEditorPane[changeSet.size()]; renderedChangeSet = new ArrayList(); int ctr = 0; for (Iterator iter = changeSet.iterator(); iter.hasNext();) { // create dynamic jeditorpane changePanes[ctr] = new JEditorPane(); changePanes[ctr].setContentType("text/html"); changePanes[ctr].setEditable(false); changePanes[ctr].addHyperlinkListener(this); String changeHTML = "<FONT FACE=\""+changeLog.swoopModel.getFontFace()+"\" SIZE="+changeLog.swoopModel.getFontSize()+">"; OntologyChange change = (OntologyChange) iter.next(); // skip SaveCheckpointChange(s) if (change instanceof SaveCheckpointChange || change instanceof RevertCheckpointChange) continue; String html = changeLog.getChangeInformation(change, ChangeLog.CHANGE_DESCRIPTION, null, new ArrayList(), null).toString(); if (!html.trim().equals("")) { renderedChangeSet.add(ctr, change); changeHTML += html; changeHTML = changeHTML.replaceAll("Undo", String.valueOf(ctr+1)); changePanes[ctr].setText(changeHTML); changePanes[ctr].setCaretPosition(0); ctr++; } } Container content = this.getContentPane(); content.removeAll(); JPanel centerPane = new JPanel(); centerPane.setLayout(new GridLayout(ctr,1)); checks = new JCheckBox[ctr]; for (int i=0; i<ctr; i++) { JPanel singleChangePane = new JPanel(); singleChangePane.setLayout(new BorderLayout()); singleChangePane.add(new JScrollPane(changePanes[i]), "Center"); checks[i] = new JCheckBox(); if (alreadyAttached.contains((OntologyChange) renderedChangeSet.get(i))) checks[i].setSelected(true); singleChangePane.add(checks[i], "West"); centerPane.add(singleChangePane); } content.setLayout(new BorderLayout()); content.add(scopePanel, "North"); content.add(new JScrollPane(centerPane), "Center"); content.add(toolbar, "South"); content.repaint(); show(); changeLog.scope = saveScope; //IMPORTANT } public void actionPerformed(ActionEvent e) { if (e.getSource()==entityScope) { attachScope = ChangeLog.ENTITY_SCOPE; this.renderChangeSet(); } if (e.getSource()==ontScope) { attachScope = ChangeLog.ONTOLOGY_SCOPE; this.renderChangeSet(); } if (e.getSource()==wkspcScope) { attachScope = ChangeLog.WORKSPACE_SCOPE; this.renderChangeSet(); } if (e.getSource()==cancelBtn) { selectedChangeSet = new ArrayList(); dispose(); } if (e.getSource()==attachBtn) { // get rendered set as final change set selectedChangeSet = this.getSelectedChanges(); dispose(); } if (e.getSource()==applyChangesBtn) { try { applyAnnotationChanges(); } catch (Exception ex) { ex.printStackTrace(); } dispose(); } } public void applyAnnotationChanges() throws Exception { // get renderedSet as final change set selectedChangeSet = this.getSelectedChanges(); SwoopModel swoopModel = changeLog.swoopModel; // save current uncommitted changes List savedUncommittedChanges = new ArrayList(swoopModel.getUncommittedChanges()); List savedCommittedChanges = new ArrayList(swoopModel.getCommittedChanges()); // apply changes, two different methods depending on serialization method if (SwoopModel.changeSharingMethod == SwoopModel.JAVA_SER) { OWLOntology ont = null; for (Iterator iter = selectedChangeSet.iterator(); iter.hasNext(); ) { OntologyChange change = (OntologyChange) iter.next(); ont = change.getOntology(); change.accept((ChangeVisitor) ont); } swoopModel.reloadOntology(ont, true); savedCommittedChanges.addAll(selectedChangeSet); swoopModel.setUncommittedChanges(savedUncommittedChanges); swoopModel.setCommittedChanges(savedCommittedChanges); } else { // add annotation changes to uncommitted list and apply swoopModel.setUncommittedChanges(selectedChangeSet); swoopModel.applyOntologyChanges(); swoopModel.setUncommittedChanges(savedUncommittedChanges); } // give success message JOptionPane.showMessageDialog(this, "Ontology Changes applied successfully", "Annotated Changes", JOptionPane.INFORMATION_MESSAGE); } public List getSelectedChanges() { List selectedChanges = new ArrayList(); for (int i=0; i<checks.length; i++) { if (checks[i].isSelected()) selectedChanges.add(renderedChangeSet.get(i)); } return selectedChanges; } public void hyperlinkUpdate(HyperlinkEvent e) { SwoopModel swoopModel = changeLog.swoopModel; SwoopFrame swoopHandler = changeLog.swoopHandler; if (e.getSource() instanceof JEditorPane) { String hLink = e.getDescription(); JEditorPane changePane = (JEditorPane) e.getSource(); if (changeLog.isURI(hLink)) changePane.setToolTipText(hLink); else changePane.setToolTipText(""); if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { if (changeLog.isURI(hLink)) { try { URI uri = new URI(hLink); if (swoopModel.getOntologyURIs().contains(uri)) { // select ontology in main swoop UI swoopHandler.ontDisplay.selectOntology(swoopModel.getOntology(uri)); } else { new SwoopLoader(swoopHandler, swoopModel).selectEntity(hLink); } } catch (URISyntaxException e1) { e1.printStackTrace(); } } // else if (hLink.startsWith("Remove from Attachment:")) { // // remove changes from change set // String hashCode = hLink.substring(23, hLink.length()); // OntologyChange change = (OntologyChange) changeLog.changeHash.get(hashCode); // this.changeSet.remove(change); // // // re-render // this.renderChangeSet(); // } } } } }