changelog.java

来自「Semantic Web Ontology Editor」· Java 代码 · 共 2,028 行 · 第 1/5 页

JAVA
2,028
字号
//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.change;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
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.JCheckBoxMenuItem;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

import org.mindswap.swoop.ModelChangeEvent;
import org.mindswap.swoop.SwoopFrame;
import org.mindswap.swoop.SwoopModel;
import org.mindswap.swoop.SwoopModelListener;
import org.mindswap.swoop.renderer.entity.ConciseFormatEntityRenderer;
import org.mindswap.swoop.renderer.entity.RDFXMLEntityRenderer;
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.change.RevertCheckpointChange;
import org.mindswap.swoop.utils.change.SaveCheckpointChange;
import org.mindswap.swoop.utils.owlapi.CorrectedRDFRenderer;
import org.mindswap.swoop.utils.rdfapi.EConnTripleVisitor;
import org.mindswap.swoop.utils.rdfapi.PrettyXMLWriter;
import org.mindswap.swoop.utils.rdfapi.TripleVisitor;
import org.mindswap.swoop.utils.ui.ChangeComparator;
import org.semanticweb.owl.io.RendererException;
import org.semanticweb.owl.model.OWLAnd;
import org.semanticweb.owl.model.OWLAnnotationProperty;
import org.semanticweb.owl.model.OWLClass;
import org.semanticweb.owl.model.OWLClassAxiom;
import org.semanticweb.owl.model.OWLDataProperty;
import org.semanticweb.owl.model.OWLDataRange;
import org.semanticweb.owl.model.OWLDataValue;
import org.semanticweb.owl.model.OWLDescription;
import org.semanticweb.owl.model.OWLDifferentIndividualsAxiom;
import org.semanticweb.owl.model.OWLDisjointClassesAxiom;
import org.semanticweb.owl.model.OWLEntity;
import org.semanticweb.owl.model.OWLException;
import org.semanticweb.owl.model.OWLIndividual;
import org.semanticweb.owl.model.OWLIndividualAxiom;
import org.semanticweb.owl.model.OWLNamedObject;
import org.semanticweb.owl.model.OWLObject;
import org.semanticweb.owl.model.OWLObjectProperty;
import org.semanticweb.owl.model.OWLOntology;
import org.semanticweb.owl.model.OWLOr;
import org.semanticweb.owl.model.OWLProperty;
import org.semanticweb.owl.model.OWLSameIndividualsAxiom;
import org.semanticweb.owl.model.OWLSubClassAxiom;
import org.semanticweb.owl.model.change.AddAnnotationInstance;
import org.semanticweb.owl.model.change.AddClassAxiom;
import org.semanticweb.owl.model.change.AddDataPropertyInstance;
import org.semanticweb.owl.model.change.AddDataPropertyRange;
import org.semanticweb.owl.model.change.AddDomain;
import org.semanticweb.owl.model.change.AddEntity;
import org.semanticweb.owl.model.change.AddEquivalentClass;
import org.semanticweb.owl.model.change.AddImport;
import org.semanticweb.owl.model.change.AddIndividualAxiom;
import org.semanticweb.owl.model.change.AddIndividualClass;
import org.semanticweb.owl.model.change.AddInverse;
import org.semanticweb.owl.model.change.AddObjectPropertyInstance;
import org.semanticweb.owl.model.change.AddObjectPropertyRange;
import org.semanticweb.owl.model.change.AddSuperClass;
import org.semanticweb.owl.model.change.AddSuperProperty;
import org.semanticweb.owl.model.change.ChangeVisitor;
import org.semanticweb.owl.model.change.OntologyChange;
import org.semanticweb.owl.model.change.RemoveAnnotationInstance;
import org.semanticweb.owl.model.change.RemoveClassAxiom;
import org.semanticweb.owl.model.change.RemoveDataPropertyInstance;
import org.semanticweb.owl.model.change.RemoveDataPropertyRange;
import org.semanticweb.owl.model.change.RemoveDomain;
import org.semanticweb.owl.model.change.RemoveEntity;
import org.semanticweb.owl.model.change.RemoveEquivalentClass;
import org.semanticweb.owl.model.change.RemoveImport;
import org.semanticweb.owl.model.change.RemoveIndividualAxiom;
import org.semanticweb.owl.model.change.RemoveIndividualClass;
import org.semanticweb.owl.model.change.RemoveInverse;
import org.semanticweb.owl.model.change.RemoveObjectPropertyInstance;
import org.semanticweb.owl.model.change.RemoveObjectPropertyRange;
import org.semanticweb.owl.model.change.RemoveSuperClass;
import org.semanticweb.owl.model.change.RemoveSuperProperty;
import org.semanticweb.owl.model.change.SetFunctional;
import org.semanticweb.owl.model.change.SetInverseFunctional;
import org.semanticweb.owl.model.change.SetSymmetric;
import org.semanticweb.owl.model.change.SetTransitive;
import org.xngr.browser.editor.XmlEditorPane;

/**
 * @author Aditya Kalyanpur
 * A file used to display Ontology Change information (i.e. change logs),
 * obtain an inverse of an Ontology Change (used for undoing committed changes)
 * and help serialize an Ontology Change in RDFXML (for sharing using Annotea)
 */
public class ChangeLog extends JPanel implements ActionListener, HyperlinkListener, SwoopModelListener, TreeSelectionListener {
	
	JEditorPane logPane;
	public SwoopModel swoopModel;
	public SwoopFrame swoopHandler;
	JCheckBoxMenuItem stayTopChk;
	JMenu saveOntMenu, saveChSetMenu, exportMenu;
	JMenuItem openMItem;
	Font tahoma = new Font("Tahoma", Font.PLAIN, 10);
	Font tahomaL = new Font("Tahoma", Font.PLAIN, 11);
	JRadioButton entityRadio, ontRadio, wkspcRadio;	
	JPanel topPanel, bottomPanel;
	JScrollPane threadTableScroll, htmlPanel;
	JCheckBox showChanges, showChkPts;
	JTreeTable changeTreeTable;
	private Map localDirty;
	JButton undoBtn, serBtn, attachBtn, deleteBtn, saveBtn;
    
	final String[] cNames  = {"Author", "Description", "Date", "Entity"};
	public int scope = 0;
	public static int ENTITY_SCOPE = 1;
	public static int ONTOLOGY_SCOPE = 2;
	public static int WORKSPACE_SCOPE = 3;
	public final static int CHANGE_DESCRIPTION = 4;
	public final static int CHANGE_RDFXML = 5;
	public final static int CHANGE_INVERSE = 6;
	public final static int CHANGE_ALIGN = 7;
	
	public ChangeLog(SwoopFrame handler, SwoopModel model) {

		this.swoopHandler = handler;
		this.swoopModel = model;
		this.localDirty = new HashMap();
		setupUI();	
	}
	
	private void setupUI() {
		
		// create radio buttons
		entityRadio = new JRadioButton("Entity");
		entityRadio.setFont(tahomaL);
		ontRadio = new JRadioButton("Ontology");
		ontRadio.setFont(tahomaL);
		wkspcRadio = new JRadioButton("Workspace");
		wkspcRadio.setFont(tahomaL);
		
		// add to button group
		ButtonGroup group = new ButtonGroup();
		group.add(entityRadio);
		group.add(ontRadio);
		group.add(wkspcRadio);
		JLabel radioLbl = new JLabel("Scope:");
		radioLbl.setFont(tahomaL);
		JPanel radioPanel = new JPanel();
		//radioPanel.setLayout(new GridLayout(1,4));
		radioPanel.add(radioLbl);
		radioPanel.add(entityRadio);
		radioPanel.add(ontRadio);
		radioPanel.add(wkspcRadio);
		
		// create checkboxes
		showChanges = new JCheckBox("Show Changes");
		showChanges.setFont(tahomaL);
		showChanges.addActionListener(this);
		showChkPts = new JCheckBox("Show Checkpoints");
		showChkPts.setFont(tahomaL);
		showChkPts.addActionListener(this);
		JPanel chkBoxPanel = new JPanel();
		chkBoxPanel.add(showChanges);
		chkBoxPanel.add(showChkPts);
		// load settings from swoopModel
		if (swoopModel!=null) {
			showChanges.setSelected(swoopModel.getEnableChangeLogDisplay());
			showChkPts.setSelected(swoopModel.isShowCheckPts());
		}
		
		// create change log pane
		logPane = new JEditorPane();
		logPane.setContentType("text/html");
		logPane.setEditable(false);
		logPane.addHyperlinkListener(this);
		
		JPanel optionPanel = new JPanel();
		optionPanel.setLayout(new GridLayout(2,1));
		optionPanel.add(radioPanel);
		optionPanel.add(chkBoxPanel);
		
		setLayout(new BorderLayout());
		add(optionPanel, "North");
		
		// create change tree table
		this.changeTreeTable = new JTreeTable(new DefaultTreeTableModel(getTreeRoot(), cNames));
		this.changeTreeTable.setFont(tahomaL);
		threadTableScroll = new JScrollPane(changeTreeTable);
		
		// set some other properties of the change tree table
		// set preferred col widths
		TableColumn column = null;
		for (int i = 0; i < changeTreeTable.getColumnCount(); i++) {
		    column = changeTreeTable.getColumnModel().getColumn(i);
		    switch (i) {
		    	case 0: column.setPreferredWidth(40); break;
		    	case 1: column.setPreferredWidth(70); break;
		    	case 2: column.setPreferredWidth(20); break;
		    	case 3: column.setPreferredWidth(60); break;
		    } 
		}

		// set default change tree params
		changeTreeTable.getTree().addTreeSelectionListener(this);
		changeTreeTable.getTree().setRootVisible(false);

		// create scroll for log pane
		htmlPanel = new JScrollPane(logPane);
		
		// create main change display pane with changeTree on top and change log pane below
		JSplitPane mainPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
		topPanel = new JPanel();
		topPanel.setLayout(new BorderLayout());
		topPanel.add(threadTableScroll, "Center");
		bottomPanel = new JPanel();
		bottomPanel.setLayout(new BorderLayout());
		bottomPanel.add(htmlPanel, "Center");
		mainPane.setTopComponent(topPanel);
		mainPane.setBottomComponent(bottomPanel);
		
		// add save checkpoint button to top of topPanel
		saveBtn = this.initButton("Save Ontology Checkpoint", "Save Checkpoint");
		topPanel.add(saveBtn, "North");
		
		// add toolbar on bottom of topPanel
		undoBtn = initButton("Undo", "Undo Selected Change(s)");
		serBtn = initButton("Serialize", "Serialize Selected Change(s) in RDF/XML");
		attachBtn = initButton("Attach", "Attach Selected Change(s) in an Annotea Annotation");
		deleteBtn = initButton("Clear", "Delete Selected Change(s) from the Log Permanently");
		
		//TODO: weirdest bug ever...make the below a JToolBar and hell breaks lose!
		JPanel toolBar = new JPanel();
		toolBar.setLayout(new GridLayout(1, 4));
		toolBar.add(undoBtn);
		toolBar.add(serBtn); 		
		toolBar.add(attachBtn);
		toolBar.add(deleteBtn);
		topPanel.add(toolBar, "South");
		
		add(mainPane, "Center");
		mainPane.setDividerLocation(200);
		
		// add actionListeners
		entityRadio.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				setScope(ENTITY_SCOPE);
			}			
		});
		ontRadio.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				setScope(ONTOLOGY_SCOPE);
			}			
		});
		wkspcRadio.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				setScope(WORKSPACE_SCOPE);
			}			
		});
	}
	
	public TreeTableNode getTreeRoot() {
		SwoopChange root = null;
		try {
			root = new SwoopChange("", new URI("/"), null, "", "", true, true);
		}
		catch (Exception ex) {
		}
		return new TreeTableNode(root);
	}
	
	/**
	 * Set the scope of the change log. Can be one of three values,
	 * Entity, Ontology or Workspace
	 * @param scope - new scope value to set
	 */
	public void setScope(int scope) {
		this.scope = scope;
		// change save checkpoint button label accordingly
		String scopeStr = "Entity";
		if (scope==this.ONTOLOGY_SCOPE) scopeStr = "Ontology";
		else if (scope==this.WORKSPACE_SCOPE) scopeStr = "Workspace";
		saveBtn.setText("Save "+scopeStr+" Checkpoint");
		this.refreshChangePane();
	}
	
	public int getScope() {
		return this.scope;
	}
	
	/**
	 * Re-render the change display pane by displaying 
	 * uncommitted and committed changes. Take into account 
	 * the current scope level
	 */
	public void refreshChangePane() {
		
		// populate the treetable based on scope and object selected in swoop
		try {
			List changeList = new ArrayList();
			switch (scope) {
			
				case 1: // ENTITY SCOPE
					if (swoopModel.getSelectedEntity()!=null) {
						URI uri = swoopModel.getSelectedEntity().getURI();
						changeList = swoopModel.getChangesCache().getChangeList(uri);						
					}
					break;
				case 2: // ONTOLOGY SCOPE
					if (swoopModel.getSelectedOntology()!=null) {
						URI uri = swoopModel.getSelectedOntology().getURI();
						changeList = swoopModel.getChangesCache().getChangeList(uri);						
					}
					break;
				case 3: // WORKSPACE SCOPE
					List changes = swoopModel.getChangesCache().getAllChanges();
					// remove all entity-scope changes
					// since entity-scope changes are subsumed by ontology-scope changes
					for (Iterator iter = changes.iterator(); iter.hasNext();) {
						SwoopChange swc = (SwoopChange) iter.next();
						if (swoopModel.getOntologyURIs().contains(swc.getOwlObjectURI())) {
							changeList.add(swc);
						}
					}
					break;
			}
			setChangeNodeTree(changeList);
		}
		catch (OWLException ex) {
			ex.printStackTrace();
		}
	}
	
	public void setChangeNodeTree(List changeList) {

		// get rootnode from changetreetable
		JTree changeTree = changeTreeTable.getTree();
		TreeTableNode rootNode = (TreeTableNode) changeTree.getModel().getRoot();
		rootNode.children = new Vector();
		logPane.setText("");
		
		// sort changes based on "timestamp" value
		SortedSet changeSet = new TreeSet(ChangeComparator.INSTANCE);
		changeSet.addAll(changeList);
		
		// populate node tree

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?