Modifications to Protege - nononing2014/repoProtege GitHub Wiki

In this section I will explain modifications to Protege. First lets see at directory structure of protege:

  • protege/org.protege.common Contains some common source code used by other applications. We don't need to modify it.
  • protege/org.protege.editor.core.application Contains source code for core application. It provides all necessary functionality like supporting new plugin, providing apis to external plugins and interacting with OWLAPI.
  • protege/org.protege.editor.owl All UI for editing ontology objects like introducing new classes and etc are provided by this API.

There are excellent sources in web to understand how to create plugin for protege. My explanation will be no where near them but I will try to explain as much as I can. There are various kinds of extension points provided by Protege to allow plugins to extend functionality of protege. Every plugin must have a plugin.xml file which declares what kind of functionality that plugin is extending. Every plugin must have something like this:

   <extension id="ExampleWorkspaceTab" point="org.protege.editor.core.application.WorkspaceTab">
		<label value="Example Tab"/>
		<class value="org.protege.editor.owl.ui.OWLWorkspaceViewsTab"/>
		<index value="X"/>
		<editorKitId value="OWLEditorKit"/>
		<defaultViewConfigFileName value="viewconfig-exampletab.xml"/>
   </extension>

These lines are conveying that id of this plugin is "ExampleWorkspaceTab", it is implementing extension point "org.protege.editor.core.application.WorkspaceTab" that is used for creating a new tab in protege. By line <class value="org.protege.editor.owl.ui.OWLWorkspaceViewsTab"/> it conveys where you can find source code of this extension. Other common extension points are org.protege.editor.core.application.ViewComponent for view component and org.protege.editor.core.application.EditorKitMenuAction for creating a new menu item. If you want to understand more about creating plugin look here for example implementations and here for wiki provided by protege for plugin development.

We created view components inside entity and class tabs. Fist take a look at modifications to xml files done by us:

plugin.xml

Updates plugin xml can be found here

    <extension id="OWLRelationList" point="org.protege.editor.core.application.ViewComponent">
        <label value="Relation"/>
        <class value="org.protege.editor.owl.ui.view.relation.OWLRelationViewComponent"/>
        <headerColor value="@org.protege.datatypecolor"/>
        <category value="@org.protege.datatypecategory"/>
        <navigates value="@org.protege.datatypecategory"/>
    </extension>

    <extension id="OWLRelatedList" point="org.protege.editor.core.application.ViewComponent">
        <label value="Related To"/>
        <class value="org.protege.editor.owl.ui.view.relation.OWLRelatedViewComponent"/>
        <headerColor value="@org.protege.classcolor"/>
        <category value="@org.protege.classcategory"/>
        <navigates value="@org.protege.classcategory"/>
    </extension>

    <extension id="OWLRelationCharacteristics" point="org.protege.editor.core.application.ViewComponent">
        <label value="Characteristics"/>
        <class value="org.protege.editor.owl.ui.view.relation.OWLRelationCharacteristicsViewComponent"/>
        <headerColor value="@org.protege.objectpropertycolor"/>
        <category value="@org.protege.objectpropertycategory"/>
    </extension>

Basically we declared three view components:

OWLRelationList Relation View Component

OWLRelatedList Related View Component

OWLRelationCharacteristics Relation Characteristic

We also declared where can you find our java implementation of those view component.

viewconfig-classestab.xml

This configuration file explains alignment of different views inside class tab of protege. Modified source code can be found here. Our modification are:

<Component label="Related To">
     <Property id="pluginId" value="org.protege.editor.owl.OWLRelatedList"/>
</Component>

Basically we are telling protege to include out OWLRelatedList view component in classes tab at a particular position.

viewconfig-entitiestab.xml

This configuration file explains alignment of different views inside entities tab of protege. Modified source code can be found here. Our modification are:

<Component label="Relations">
      <Property id="pluginId" value="org.protege.editor.owl.OWLRelationList"/>
</Component>

Basically we are telling protege to include out OWLRelationList view component in entities tab at a particular position.

Our views

Our main modification are included in folder protege/org.protege.editor.owl/src/main/java/org/protege/editor/owl/ui/view/relation we created this folder to create new views that will be used for UI supporting our proposed syntax. As you can see this folder contains java files mentioned in plugin.xml earlier. I will try to explain UI modification to the best of my ability. Protege uses java swing to create its UI so some basic knowledge on creating ui using swing will improve understanding of my modification. That being said lets see each of the ui component created by us:

Relation List Component

This component create this UI:

Relation View Component

We modified and created several files to support our UI. I will explain each of the files and I will explain each line in comment please read comments for more clear understanding.

OWLRelationViewComponent.java

This file implements entry point for our UI. This is pointed in plugin.xml so protege can load this view. Complete source code can be found here. A view component in Protege is extension to view class of swing in java.

//Package on which this file is included
package org.protege.editor.owl.ui.view.relation;

//Some imports. I don't want to clutter this documentation with all imports so I have include only one import. For complete set of imports see original file.
import org.protege.editor.owl.ui.list.OWLAxiomList;

// Every view component in Protege must extend AbstractOWLViewComponent. As it provides necessary APIs for proper working of view component in question.
public class OWLRelationViewComponent extends AbstractOWLViewComponent {

        // Version ID
        private static final long serialVersionUID = -4515710047558710080L;

        // java logger for debugging and outputting error messages. 
        private static final Logger log = Logger.getLogger(OWLRelationViewComponent.class);

        // OWLRelationList is extension to JList of swing library created by us display a list of relations.
        private OWLRelationList list;

        // Holds current ontology.
        private OWLOntology actOnt;
	
        // Declares a relation change listener which will be called when a relation is changed. This is explained in section concerning OWLAPI.
	private OWLRelationChangeListener relListner = new OWLRelationChangeListener(){
		public void relationChanged(String changeType, OWLRelation rel){
			reload();
		}
	};
	
        // Listener that will be called when selection in a list will be changed. This is standard listener provided by swing library of java.
	private ListSelectionListener relSelListener = new ListSelectionListener(){
        
        // Function that is called when a selection is changed
        public void valueChanged(ListSelectionEvent e) {
           
            // Selection Model in protege stores which entity is selected in UI. I have made some modifications to selection model also I will explain it later. In this line I am telling selection model to store selected relation in it's memory.
            getOWLWorkspace().getOWLSelectionModel().setSelectedRelation(list.getSelectedValue());
        }
    };
	

// Called when initializing this view.	
    @Override
    protected void initialiseOWLView() throws Exception {

        // See swing documentation for this line.
        setLayout(new BorderLayout());

	// Create a new OWLRelationList that is extension to JList of swing. It is created by us and I will explain it later.
	list = new OWLRelationList(getOWLEditorKit());

        // Get active ontology from protege editor kit.
	actOnt = getOWLEditorKit().getOWLModelManager().getActiveOntology();

        // Add relation chnage listener in current ontology. I explained this in explanation of OWLAPI.
	actOnt.addRelationChangeListner(relListner);

        // Function declared later int this file to reload our UI.
	reload();

        // Our UI has two buttons in top they are to delete a relation and add a relation setup both buttons.
	setupActions();

        // Create a scroll pane from list of relation. See documentation of swing library.
	add(ComponentFactory.createScrollPane(list));

        // Add selection listener to given list. It is API provided by JList of swing. It will be triggered when a selcetion is changed
	list.addListSelectionListener(relSelListener);
    }

       // Called when this view is being deleted.
	@Override
	protected void disposeOWLView() {

                //Remove all selection listener
		list.removeListSelectionListener(relSelListener);
		actOnt.removeRelationChangeListner(relListner);
	}
	
        // Reload our UI
	private void reload(){

        // Get active ontology
        actOnt = getOWLModelManager().getActiveOntology();

        // Get set of relations from active ontology.
        java.util.List<OWLRelation> relationList = actOnt.getAllRelations();

        // Include all these relations in our list thereby displaying all relations in active ontology.
        list.setListData(relationList.toArray(new OWLRelation[relationList.size()]));
    }
	
	    private void setupActions() {

            // Add new relation button. Provided by swing in java.
        final DisposableAction addDatatypeAction = new DisposableAction("Add relation", OWLIcons.getIcon("datarange.add.png")) {
            
            private static final long serialVersionUID = 7152977701137488187L;

            // Create a new relation.
            public void actionPerformed(ActionEvent event) {
                createNewRelation();
            }

            public void dispose() {
                // do nothing
            }
        };

        // Create a delete button.
        final OWLSelectionViewAction deleteDatatypeAction = new OWLSelectionViewAction("Delete relation", OWLIcons.getIcon("datarange.remove.png")) {

            /**
             * 
             */
            private static final long serialVersionUID = 5359788681251086828L;

            // Delete selected relation
            public void actionPerformed(ActionEvent event) {
                deleteRelation();
            }

            // Don't activate this button unless something is selected/highlighted
            public void updateState() {
                // @@TODO should check if this is a built in datatype
                setEnabled(list.getSelectedIndex() != -1);
            }


            public void dispose() {
                // do nothing
            }
        };

        // Add both buttons in our view
        addAction(addDatatypeAction, "A", "A");
        addAction(deleteDatatypeAction, "B", "A");
    }

        // Called when a new relation button is pressed.
	public void createNewRelation(){
                // Invoke newRelationCreationPanel. I will explain this later.
		newRelationCreationPanel.showDialog(getOWLEditorKit(), "Please enter a datatype name");
	}
	
        // Delete all selected relations.
	public void deleteRelation(){
		for(OWLRelation rel : list.getSelectedOWLObjects())
                        // Remove relation is explained in OWLAPI documentation.
			actOnt.removeRelation(rel.toString());
	}
}

OWLRelationList.java

OWLRelationList is extension to JList used for crating a list of relation. It is used in above view. Complete source code after modification can be found here:

//Package on which this file is included.
package org.protege.editor.owl.ui.view.relation;

//Some imports. I don't want to clutter this documentation with all imports so I have include only one import. For complete set of imports see original file.
import org.protege.editor.owl.OWLEditorKit;

// Extends JList of swing library.
public class OWLRelationList extends JList<OWLRelation> {
    private static final long serialVersionUID = -817749022854204056L;


    public OWLRelationList(OWLEditorKit owlEditorKit) {
        // Get simple cell renderer. This function is provided by protege to create a renderer for JList. We slightly modified it to render our relations, we will explain this later.
        setCellRenderer(new OWLCellRendererSimple(owlEditorKit));
    }

//Get tool tip message for a relation in a list.
    public String getToolTipText(MouseEvent event) {
        int index = locationToIndex(event.getPoint());
        if (index >= 0){
            Object element = getModel().getElementAt(index);
            if (element != null && element instanceof OWLRelation){
                return ((OWLRelation)element).getName();
            }
        }
        return null;
    }


// Set selected values in given list
    public void setSelectedValues(Set<OWLRelation> owlRelations, boolean shouldScroll) {
        getSelectionModel().clearSelection();
        if (getSelectionMode() == ListSelectionModel.MULTIPLE_INTERVAL_SELECTION){
            int firstIndex = -1;
            for (int i=0; i<getModel().getSize(); i++){
                if (owlRelations.contains(getModel().getElementAt(i))){
                    getSelectionModel().addSelectionInterval(i, i);
                    if (firstIndex == -1){
                        firstIndex = i;
                    }
                }
            }
            if (shouldScroll && firstIndex != -1){
                scrollRectToVisible(new Rectangle(getCellBounds(firstIndex, firstIndex)));
            }
        }
    }

// Get selected objects in given list
    @SuppressWarnings("unchecked")
    public java.util.List<OWLRelation> getSelectedOWLObjects(){
        List<OWLRelation> sel = new ArrayList<OWLRelation>();
        for (Object o : getSelectedValues()){
            sel.add((OWLRelation) o);
        }
        return sel;
    }
}

newRelationCreationPanel.java

Popup that will be displayed when new relation button is pressed. Complete source code can be found [here](https://github.com/khageshpatel/repoProtege/blob/master/protege-master/org.protege.editor.owl/src/main/java/org/protege/editor/owl/ui/view/relation/newRelationCreationPanel.java newRelationCreationPanel). We only use swing library to create this popup. I have not included source code for this file in our documentation because you can understand it easily after some internet browsing.

OWLRelationCharacteristicsViewComponent.java

This view component is used for declaring various attributes of a relation. Complete source code can be found [here](https://github.com/khageshpatel/repoProtege/blob/master/protege-master/org.protege.editor.owl/src/main/java/org/protege/editor/owl/ui/view/relation/OWLRelationCharacteristicsViewComponent.java OWLRelationCharacteristicsViewComponent). Again only thing new in this file from previous files is use of swing library. It can be understood by going through swing documentation.

SelectedEntityCardView.java

This file is responsible for changing the view in right panel of entities tab. We wanted to modify it such that when a relation is changed it shows OWLRelationCharacteristicsViewComponent. Complete source can be found here. Our modifications are:

// Import this as it is required.
import org.protege.editor.owl.model.selection.OWLRelationSelectionListener;

// Panel name for relations
private static final String RELATIONS_PANEL = "Relations";

//Create a listener that will be called when a selection is changed in relation panel.
private OWLRelationSelectionListener RelSelListener = new OWLRelationSelectionListener() {
				public void selectionChanged() throws Exception {
                processRelationSelection();
            }
	};

 protected void initialiseOWLView() throws Exception {
         ::
         // Add our relation selection listener
	 getOWLWorkspace().getOWLSelectionModel().addListener(RelSelListener);
         ::
         // Add characteristic view component that we created earlier to list of panels. 
         addPane(RELATIONS_PANEL,
                "/selected-entity-view-relation-panel.xml",
                "org.protege.editor.owl.ui.view.selectedentityview.relations",
                reset);

 }

// Whenever a relation selection change occur select our relation panel
private void processRelationSelection(){
	selectPanel(RELATIONS_PANEL);
}

// When this view is deleted remove out list selection change listener
  protected void disposeOWLView() {
        ::
	getOWLWorkspace().getOWLSelectionModel().removeListener(RelSelListener);
  }

OWLCellRendererSimple.java

As mentioned earlier we used simple cell renderer to render list of relations. So we need to modify simple cell renderer to render our relations. Complete source code can be found here. Our modifications are:

// Import these libraries as we will use it later
import org.protege.editor.owl.ui.OWLIcons;
import org.semanticweb.owlapi.model.OWLRelation;

private void setText(Object value, JLabel renderer) {
        ::
        // If entity you are rendering is a OWLRelation display its name as text
	else if(value instanceof OWLRelation){
		OWLRelation obj = (OWLRelation) value;
		renderer.setText(obj.getName());
	}
}

private void setIcon(Object value, JLabel renderer) {
        ::
        // If entity you are rendering is OWLRelation put "datarange.png" as its icon.
	else if(value instanceof OWLRelation){
		renderer.setIcon(OWLIcons.getIcon("datarange.png"));
	}
}

OWL Selection Model

Selection model is responsible for managing selection of various entities in Protege UI.

OWLRelationSelectionListener.java

We defined a interface of a selection listener that will be triggered when a change relation selection has occurred. Complete source code can be found here.

OWLSelectionModel.java

This file includes set of APIs provided by OWL selection model. Complete source code can be found here. We introduced four new methods in OWL selection model:

getLastSelectedRelation(): returns last selected listener.

setSelectedRelation(OWLRelation rel): Set selected relation

addListener(OWLRelationSelectionListener listener): Add a selection listener

removeListener(OWLRelationSelectionListener listener): Remove a selection listener

OWLSelectionModelImpl.java

This file includes implementation of APIs declared in OWLSelectionModel.java. Complete source code can be found here. Our modification are:

// A list maintaining listeners that need to be triggered when a selection is changed
private List<OWLRelationSelectionListener> relListeners;

//Last selected relation
private OWLRelation lastRelation;

public OWLSelectionModelImpl() {
     ::
     // Initialize list of selection listeners.
     relListeners = new ArrayList<OWLRelationSelectionListener>();
     ::
}

// Add a listener to list of listener
public void addListener(OWLRelationSelectionListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("Listener must not be null!");
        }
        relListeners.add(listener);
}

// Remove a listener
public void removeListener(OWLRelationSelectionListener listener) {
     relListeners.remove(listener);
}

// Set last selected relation
public void setSelectedRelation(OWLRelation rel){
	if (rel == null) {
            if (lastRelation != null) {
                updateSelectedRelation(null);
            }
        }
        else {
            if (lastRelation == null) {
                updateSelectedRelation(rel);
            }
            else if (!rel.toString().equals(lastRelation.toString())) {
                updateSelectedRelation(rel);
            }
        }
}

// Set last selected relation and fire all change listeners
private void updateSelectedRelation(OWLRelation rel){
	lastRelation = rel;
	fireRelationSelectionChanged();
}

// Fire all relation selection listeners added in this model
private void fireRelationSelectionChanged(){
		for (OWLRelationSelectionListener listener : new ArrayList<OWLRelationSelectionListener>(relListeners)) {
            try {
                listener.selectionChanged();
            }
            catch (Exception e) {
                logger.warn("BAD LISTENER: (" + listener.getClass().getSimpleName() + ") ");
                ProtegeApplication.getErrorLog().handleError(Thread.currentThread(), e);
            }
        }
}

Creating relation between two concepts

Here we will introduce view created for introducing relations between two concepts.

OWLRelatedViewComponent.java

This is main java file used fo creating this panel: . Complete source code can be found [here] (https://github.com/khageshpatel/repoProtege/blob/master/protege-master/org.protege.editor.owl/src/main/java/org/protege/editor/owl/ui/view/relation/OWLRelatedViewComponent.java "Related View component"). All the line in this file are either introduced earlier or can be found in swing library documentation therefore I believe reader can go through this file on his/her own.

newRelatedCreationPanel.java

This declares popup that will be triggered when you press new button in this view. Here is complete source code of this file. Here we use split pane of swing library to create our popup. All APIs in this file come from swing library therefore not much explanation is required.

⚠️ **GitHub.com Fallback** ⚠️