You are on page 1of 11

2/11/2016

PluginAnatomyProtegeWiki

FromProtegeWiki

Contents
1Introduction
2Thevacuousplugininfiveminutes
2.1Build.xml
2.2MANIFEST.MF
2.3CompileandRun
3WritingViewandTabPlugins
3.1AddingaViewPlugintothePlugin.xmlfile
3.2LibrariesandtheBundleClasspath
3.3TabPluginsandtheViewconfig.xmlFile
3.3.1Step1:Declaretheplugin
3.3.2Step2:Layouttheviewsintheplugin
3.3.3Step3:Saveaconfigurationfile
3.3.4Step4:Testtheresults
4AddingMenuPlugins
5UsingaReasoner
6AdvancedTopics
6.1AddingNewPluginTypes
6.1.1ThePluginConsumer
6.1.2ThePluginLoader
6.1.3ThePlugin
6.1.4ThePluginInstance
6.2Frames,FrameSections,andRows
6.2.1FrameListsandFrames
6.2.2FrameSections
6.2.3FrameSectionRows
7Glossary

Introduction
Thepurposeofthiswebpageistodescribesomeofthekeyingredientsofaplugin.Thepagewillbedirectedbythequickdevelopmentofapluginandcanindeedbeused
asaquickstartguide.InordertofocusattentiononthecorepluginconceptswewillusethelowestcommondenominatorofJavadevelopmenttoolsandthistutorialwill
notuseaJavaIDE.WewillassumethatthereaderhasanunderstandingofJavadevelopmentandknowshowtofollowalonginhisfavoriteIDE.Formoreinformation
abouthowtoworkwithprotege4inanIDEIwilldirectthereadertothispage.Itispossibleforanexperienceddevelopertoskiptheantscriptssimplyfollowalonginan
IDEbutwewouldstillrecommendabuildfileforthefinalversion.
Thesourcesforthefirstplugin(theexampletab)canbefoundhere(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/plugin/trunk/org.protege.editor.owl.examples.tab).Youcaneitherchecktheseoutfromsvnandusethisasa
guideforreadingthetextorbuildthisprojectinaseriesofstepbystepstagesasdescribedbelow.Ifyoustartfromthecheckedoutversionthenyoucanbuildtheproject
byfollowingthedirectionshere.

Thevacuousplugininfiveminutes
Icreateda(vacuous)pluginfromscratch,installeditandranitinjustunderfourminutes.ThereisalsoanewexpereimentalquickstartguideforstartinganewProtege5
pluginwithmavenwhichwillprobablyevolveintothenewrecommendedstrategy.
Thesimplest(trivial)plugincanbebuiltfromsourcesinthefollowinglayout:
build.xml
METAINF
MANIFEST.MF
lib
resources
src

AswewillseeevenwithoutanyjavasourcesthisisasufficientbasisforbuildingapluginthatisrecognizedbyProtege4.Thereareonlytwofilesinthissourcetree
thebuild.xmlfileandtheMANIFEST.MF.Thesefilescanbequicklyputtogetherfromtemplates.

Build.xml
Thetemplateforthebuild.xmlfilecanbedownloadedfromhere(http://smiprotege.stanford.edu/repos/protege/protege4/protegebase/trunk/etc/templatepluginbuild.xml)
.Onlytwothingsneedtobechangedinthisbuildfile.Theycanbefoundbysearchingforthestring"CHANGEME"inthefile.Thefirstthingtochangeisthenameofthe
project.Iwillcalltheprojecttheplugintutoiralproject:
<projectname="plugintutorial"default="install"basedir=".">

Thenextsettingthatmustalmostalwaysbechangedisthenameoftheplugin.Inthiscase,thebuild.xmlalreadyhastherightnameforthepluginbutthisistheonlyplugin
forwhichthiswillbetrue:
<propertyname="plugin"value="org.protege.editor.owl.examples.tab"/>

Withtheseadjustmentsthebuild.xmlfileisready.

MANIFEST.MF
ThetemplatefortheMANIFEST.MFfilecanbedownloadedfromhere(http://smiprotege.stanford.edu/repos/protege/protege4/protegebase/trunk/etc/template
manifest.mf).Onlyfivethingsneedtobechangedinthisfiletomakeituseableandtwoareoptional.Thesecanbefoundbysearchingforthestring"CHANGEME"inthe
file.Thefirstchangeistosetthedisplaynamefortheplugin:
BundleName:TutorialPlugin

ThisisthenamethatisseenwhenProtege4startsupandinseveralpluginconfigurationscreens.Theseccondthingtochangeisthesymbolicnameoftheplugin.Theusual
defaultistousesthesamenameasthepluginnameinthebuild.xmlfile:
BundleSymbolicName:org.protege.editor.owl.examples.tab;singleton:=true

Notethe"singleton:=true"linethisisimportantsincemostProtege4pluginswillonlyworkiftheyareinstantiatedexactlyonce.Thenextthingstochangearethebundle
description,thevendorandthedocumentationurl:
BundleDescription:Asimplepluginforaplugindevelopmenttutorial
BundleVendor:TheProtegeDevelopmentTeam
BundleDocURL:www.perhaps.i.donthaveoneyet.com

Actuallythevendorandthedocurlareoptionalandcanbedeleted.TheMANIFEST.MFfileisnowready.
http://protegewiki.stanford.edu/wiki/PluginAnatomy

1/11

2/11/2016

PluginAnatomyProtegeWiki

CompileandRun
Beforewecanstart,wemustsetthePROTEGE_HOMEenvironmentvariabletopointtoaProtege4distribution.Thispagehasdirectionsonhowtodothisindifferent
operatingsystemsbutfornowIwillassumethatweareonaunix(orosx)system.Inthatcase,thesystemvariablecanbesetwithasimplecommand
exportPROTEGE_HOME=/Users/tredmond/Desktop/Protege_4.1_beta

Thisvacuouspluginisnowreadytocompileandrun.AssumingthatthePROTEGE_HOMEenvironmentvariableissetcorrectly,thisplugincanbecompiledwiththe
simplecommand
antinstall

Thefulltextofthebuildsessionisasfollows:
[tredmond@Andromedaorg.protege.editor.owl.examples.tab]$antinstall
Buildfile:build.xml
init:
[mkdir]Createddir:/private/tmp/org.protege.editor.owl.examples.tab/build
[mkdir]Createddir:/private/tmp/org.protege.editor.owl.examples.tab/build/classes
[mkdir]Createddir:/private/tmp/org.protege.editor.owl.examples.tab/build/classes/lib
[mkdir]Createddir:/private/tmp/org.protege.editor.owl.examples.tab/build/lib
checkProtegeLibs:
[echo]UsingProtegeHome=/Andromeda/Users/tredmond/dev/workspaces/protege4/owleditor/build/dist/equinoxtofindprotegejars
checkProtegeLibsAndReport:
buildlibs:
[unjar]Expanding:/Andromeda/Users/tredmond/dev/workspaces/protege4/owleditor/build/dist/equinox/bundles/org.protege.common.jarinto/private/tmp/org.protege.editor.owl.examples.tab/build
compile:
build.manifest:
[copy]Copying1fileto/private/tmp/org.protege.editor.owl.examples.tab/build
copy.resources:
[mkdir]Createddir:/private/tmp/org.protege.editor.owl.examples.tab/build/classes/METAINF
[copy]Copying1fileto/private/tmp/org.protege.editor.owl.examples.tab/build/classes/METAINF
jar:
[jar]Buildingjar:/private/tmp/org.protege.editor.owl.examples.tab/build/org.protege.editor.owl.examples.tab.jar
install:
[delete]Deletingdirectory/Andromeda/Users/tredmond/dev/workspaces/protege4/owleditor/build/dist/equinox/configuration/org.eclipse.core.runtime
[delete]Deletingdirectory/Andromeda/Users/tredmond/dev/workspaces/protege4/owleditor/build/dist/equinox/configuration/org.eclipse.osgi
[copy]Copying1fileto/Andromeda/Users/tredmond/dev/workspaces/protege4/owleditor/build/dist/equinox/plugins
BUILDSUCCESSFUL
Totaltime:2seconds
[tredmond@Andromedaorg.protege.editor.owl.examples.tab]$

IfthePROTEGE_HOMEenvironmentvariableisnotsetcorrectlytheuserwillinsteadseethefollowing:
BUILDFAILED
/private/tmp/org.protege.editor.owl.examples.tab/build.xml:74:missingprotegelibraries

Wecannowlookatwhatthebuildhasdonebyexploringtheprojectdirectorytree.

Weseethefollowingelements:
TheClassTreeis(approximately)aflattenedviewoftheplugin(thejarfile).Generallythislargelyconsistsofthe.classfilesthathavebeencompiledfromthejava.
Butsincewehavenotwrittenanyjavayetthisisnotfound.Inaddition,thiswillcontainresourcesneededbythepluginandlibrariesthatthepluginneedsbutwhich
cannotbefoundinotherProtegeplugins.
TheGeneratedLibrarieswhichareextractedfromProtegeplugins.ThisisneededbecauseofadifferencebetweenhowJavaandOSGigetresourcesoutofJar
files.OSGiallowsabundle(whichisaimplementedasajarfile)tocontainotherjarfiles.Ifthebundleclasspathisconfiguredcorrectly,OSGiwillloadclassesfrom
thosejarsinjars.ButJavadoesnothavethiscapability.SothebuildscriptextractsthejarfilesoutoftheOSGibundlesthatwillbeneededtocompilethebundle.
NotethatthesejarfilesarenotcopiedtotheclasstreebecausetheProtege4/OSGienvironmentwillmaketheclassesandresourcesofthesejarfilesavailable.
TheProtege4Pluginthisisthefinalartifactofthebuildprocess.Becausewehaverun"antinstall"ithasalsobeeninstalledintheProtegedistribution.
Ifthedeveloperisstillwithmethenheisnowreadytoruntheplugin.GototheProtegedistribution(theonepointedtobythePROTEGE_HOMEenvironmentvariable)
andrunit.Weareparticularlyinterestedintheconsoleoutputbecausethisisgoingtobetheonlyindicationthatthispluginisrecognizedatall.Theconsoleoutputshould
looklikethis:
StartingProtege4OWLEditor(Version4.1.111)
Platform:
Java:JVM1.5.0_16b06284Memory:207M
Language:en,Country:US
Framework:Eclipse(1.4.0)
OS:MacOSX(10.5.6)
Processor:ppc
InstalledpluginPelletReasoner
InstalledpluginDLQueryTab
InstalledpluginOwlvizPlugin
Installedpluginowleditor
InstalledpluginTutorialPlugin
InstalledpluginTheOWLAPI
InstalledpluginFactplusplusPlugin

TutorialPluginPluginhasnoplugin.xmlresource

InthisoutputweseethattheTutorialPluginhasbeenrecognizedandinstalled.Inadditionthereisainformationalmessagethattheplugin.xmlfilehasnotbeenfound.This
isalmostalwaysindicatesaproblembecausemostProtege4pluginsdependonaplugin.xmlresource.Wewilldescribehowtheplugin.xmlfileisgeneratedinthenext
sections.
http://protegewiki.stanford.edu/wiki/PluginAnatomy

2/11

2/11/2016

PluginAnatomyProtegeWiki

WritingViewandTabPlugins
ThepreviouspluginaddednofunctionalitytoProtege4.Wearenowgoingtodescribehowtoremedythissitutaion.SofarwehavenotmissedtheJavaIDEbutitisnow
whenwestartwritingabitofJavacodethattheJavaIDEwouldreallyshine.Buttoillustratethemainconcepts,wewillcontinuetoshowhowtobuildthepluginwithout
anydevelopmentenvironmentotherthanthatprovidedbythecoreJavatools.

AddingaViewPlugintothePlugin.xmlfile
Recallthatpreviouslywhenweranourplugin,Protege4complainedthattherewasnoplugin.xmlfile.Theplugin.xmlfilecontainsadeclarationofthewaysinwhichthe
pluginwillextendtheProtege4capabilitiesand(moreadvanced)thewaysinwhichtheplugincapabilitiescanbeextendedbyotherplugins.Wewillstartbyaddinga
declarationthatthispluginwillimplementaProtegeView.
SofirstwewillgiveadefinitionofaProtegeview.ThepurposeofaProtegeviewistoprovideaviewofsomeaspectofanontology.IntheProtegeinterface,aProtege
viewiseasilyrecognized.Ithasaclearlydefinedborder.AtthetopofaProtegeviewisatitlebarandacollectionofbuttonsallowingtheuserto
splittheprotegeviewintotwocopiesofthesameviewoneabovetheother,
splittheprotegeviewintotwocopiesofthesameviewonebesidetheother,
floattheviewabovetheProtegeclientsothatitisvisibleinanycontext,
closetheviewremovingitfromthetabthatcontainsit.

AnexampleofatypicalProtegeviewisshownbelow.

InordertodeclareourintentthatthispluginimplementaProtegeview,weaddthefollowingplugin.xmlfiletotherootoftheprojecttree:
<?xmlversion="1.0"encoding="UTF8"standalone="no"?>
<?eclipseversion="3.0"?>
<plugin>
<extensionid="ExampleViewComponent"
point="org.protege.editor.core.application.ViewComponent">
<labelvalue="ExampleViewComponent"/>
<classvalue="org.protege.editor.owl.examples.tab.ExampleViewComponent"/>
<categoryvalue="@org.protege.ontologycategory"/>
</extension>
</plugin>

Thisplugin.xmlfilestatesthatthispluginismakingasingleextensiontotheProtege4capabilities.Wewillcoverthemeaningofthepartsofthisextensiondeclarationline
byline.Thefirstlinedefinestheidoftheextension.ThisparticularextensioniscalledtheExampleViewComponent.Theseconddecleration,
point="org.protege.editor.core.application.ViewComponent",

stateswhattheextensionistryingtodo.Thisextensionisattemptingtoimplementthefunctionalityrepresentedbytheextensionpointwiththename
org.protege.editor.core.application.ViewComponent.

ThelabeldeclarationtellsProtegewhattoputinthetitlebaroftheview.Theclassdeclarationindicateswhichclassimplementsthefunctionalityneededbythisview.We
willgointotheimplementationofthatclassshortly.FinallythecategorydeclarationtellsProtegewhichmenuundertheViewmenushouldcontainthisview.

AverysimpleviewcanbewrittenbyextendingtheclassAbstractOWLViewComponentandimplementingthemethodsinitialiseOWLViewanddisposeOWLView.Avery
simplesuchimplementationcanbefoundhere(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/plugin/trunk/org.protege.editor.owl.examples.tab/src/org/protege/editor/owl/examples/tab/ExampleViewComponent.java)
.Nowthisplugindependsonalibrarythatcanbefoundhere(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/plugin/trunk/org.protege.editor.owl.examples.tab/lib/examplelib.jar).Thislibraryshouldbedepositedinthelib
directoryoftheproject.Thislibraryistrivialanditsonlypurposeistoshowhowtousealibraryinaplugin.Thedirectorytreeoftheprojectshouldnowlooklikethis:

http://protegewiki.stanford.edu/wiki/PluginAnatomy

3/11

2/11/2016

PluginAnatomyProtegeWiki

Atthispointtheantinstalloperationwillcompile,buildandinstallthenewpluginwiththe"antinstall"command.Buttheinstalledpluginwon'truncorrectlyandwewill
showhowtofixthisbelow.

LibrariesandtheBundleClasspath
Afterweinstalltheplugin,wecanstartProtegetotrytousethe"ExampleViewComponent".IfyouclickontheViewmenuandthenselect"OntologyViews"youwillsee
the"ExampleViewComponent"listedthere.HoweveronselectingthisviewandtryingtoplaceontheProtegescreen,thefollowingerrorwillarise:
Errorlogged
java.lang.NoClassDefFoundError:org/protege/owl/example/Metrics

atjava.lang.Class.getDeclaredConstructors0(NativeMethod)

atjava.lang.Class.privateGetDeclaredConstructors(Class.java:2357)

atjava.lang.Class.getConstructor0(Class.java:2671)

atjava.lang.Class.newInstance0(Class.java:321)

atjava.lang.Class.newInstance(Class.java:303)
...

Ifwelookattheplugincontentswiththe"jartf"commandthenwewillseethatthebuildfilecorrectlyputtheexamplelib.jarintotheplugin:
[tredmond@BlackHoleorg.protege.editor.owl.examples.tab]$jartfbuild/org.protege.editor.owl.examples.tab.jar
METAINF/
METAINF/MANIFEST.MF
lib/
org/
org/protege/
org/protege/owl/
org/protege/owl/examples/
org/protege/owl/examples/tab/
lib/examplelib.jar
org/protege/owl/examples/tab/ExampleViewComponent.class
plugin.xml
[tredmond@BlackHoleorg.protege.editor.owl.examples.tab]$

TheproblematthispointisintheMANIFEST.MFfile.TheBundleClasspathlineisasfollows:
BundleClassPath:.

Toincludetheexamplelib.jarinthejarfile,theBundleClasspathlinemustbemodifiedtoincludethislibrary:
BundleClassPath:.,lib/examplelib.jar

Notethatusingacolonorasemicoloninsteadofthecommadoesnotwork.Alsoentering./lib/examplib.jardoesnotworkeither.Thisistheosgimechanismformaking
thislibraryavailabletothisplugin.NotethatsincetheMANIFEST.MFfiledoesnothaveanExportPackagedeclaration,theseclasseswillonlybevisiblewithintheplugin
andwillnotbeexportedtoanyotherpluginintheProtege4environmeht.ThisispartofthepluginisolationprovidedbyOSGithatallowsdifferentpluginstousedifferent
librarieswithoutconflicts.
NowthepluginworkscorrectlyandIcaninstalltheviewintotheActiveOntologyTab:

TabPluginsandtheViewconfig.xmlFile
TheothermostcommonplugintypeistheProtegetab.InordertomakeaProtegetab,thedeveloperneedstogenerateanduseaviewconfig.xmlfilefortheproject.Inthis
sectionwewillshowhowtodothis.ItturnsoutthatatabcanusuallybeputtogetherwithoutwritinganyJavacode.Thestepsforwritingatabpluginare
1.addadeclarationofthetabpluginintheplugin.xmlfile.
2.startProtegeandgraphicallyconfigurethetabinquestion.
3.savetheconfigurationandincludeitwiththesourcefilesforthetab.
4.testbyrestartingProtegeandrunningthetabwiththedefaultconfiguration.
Thesestepsaredescribedinmoredetailbelow.
Step1:Declaretheplugin
Thefirstthingthatthatneedstobedoneistodeclarethetabintheplugin.xmlfile.
<?xmlversion="1.0"encoding="UTF8"standalone="no"?>
<?eclipseversion="3.0"?>
<plugin>
<extensionid="ExampleViewComponent"
point="org.protege.editor.core.application.ViewComponent">
<labelvalue="ExampleViewComponent"/>
<classvalue="org.protege.editor.owl.examples.tab.ExampleViewComponent"/>
<categoryvalue="@org.protege.ontologycategory"/>

http://protegewiki.stanford.edu/wiki/PluginAnatomy

4/11

2/11/2016

PluginAnatomyProtegeWiki

</extension>
<extensionid="ExampleWorkspaceTab"
point="org.protege.editor.core.application.WorkspaceTab">
<labelvalue="ExampleTab"/>
<classvalue="org.protege.editor.owl.ui.OWLWorkspaceViewsTab"/>
<indexvalue="X"/>
<editorKitIdvalue="OWLEditorKit"/>
<defaultViewConfigFileNamevalue="viewconfigexampleTab.xml"/>
</extension>
</plugin>

AnimportantlineintheabovedeclarationofthetabisthedefaultViewConfigFileName.Thisnamesaresourcethattheprotegepluginwilllookfortocreatethedefault
layoutofthetab.
Step2:Layouttheviewsintheplugin
Wecannowcompilethispluginandinstallitasbefore.NowwhenwerunProtege4,wewillseeanewtabcalledthe"ExampleTab"inthetabsmenu(Window>Tabs).
Enablethistab.SincewehavenotyetcreatedtheviewconfigexampleTab.xmlfile,youwillseethatthetabisempty.
Nowinstallandlayoutsomeviewsintothistab.InmycaseImadetheviewslooklikethis:

Step3:Saveaconfigurationfile
NowintheWindowmenuselect"ExportCurrentTab"andsavethefileas
viewconfigexampleTab.xml

intheprojectdirectory.InmycasetheviewconfigexampleTabfilelookedlikethis:
<?xmlversion="1.0"encoding="UTF8"?>
<layout>
<VSNodesplits="0.50.5">
<CNode>
<Componentlabel="Assertedclasshierarchy">
<Propertyid="pluginId"value="org.protege.editor.owl.OWLAssertedClassHierarchy"/>
</Component>
</CNode>
<CNode>
<Componentlabel="ExampleViewComponent">
<Propertyid="pluginId"value="org.protege.editor.owl.examples.tab.ExampleViewComponent"/>
</Component>
</CNode>
</VSNode>
</layout>

NowbeforewecompletethisProtegesession,gototheWindowmenuandclick"Resetselectedtabtodefaultstate".Youwillseethatthetabisnowemptyagain.Nowexit
Protege.
Thedirectorytreeoftheprojectshouldnowlooklikethis:

http://protegewiki.stanford.edu/wiki/PluginAnatomy

5/11

2/11/2016

PluginAnatomyProtegeWiki

Step4:Testtheresults
Installthepluginagain.NotethatthebuildscriptautomaticallyfoundtheviewconfigexampleTab.xmlfileandputitintotheplugin:
[tredmond@BlackHoleorg.protege.editor.owl.examples.tab]$jartfbuild/org.protege.editor.owl.examples.tab.jar
METAINF/
METAINF/MANIFEST.MF
lib/
org/
org/protege/
org/protege/owl/
org/protege/owl/examples/
org/protege/owl/examples/tab/
lib/examplelib.jar
org/protege/owl/examples/tab/ExampleViewComponent.class
plugin.xml
viewconfigexampleTab.xml
[tredmond@BlackHoleorg.protege.editor.owl.examples.tab]$

RunProtegeandgototheExampleTab.Itisempty?Thereasonforthisisthatthetabhasbeencustomizedtohavenothinginitfromthelastsession.Clickonthetabs
menuandclickon"Resetselectedtabtodefaultstate".Nowyouwillseetheviewsthatweconfiguredinthetabbefore.Thisisnowthedefaultstateforthetabanditwill
bewhatotherusersseewhentheyusethispluginforthefirsttime.

AddingMenuPlugins
Ihavecreatedasmallmenuprojecthere(http://smiprotege.stanford.edu/repos/protege/protege4/misc/examples/org.protege.example.menu/trunk)thatshowshowtocreate
severaldifferentmenutypes.Laterwewillusethisprojectastheexamplethatdrivesthiswikipage.
AddinganewmenutoProtege4.1isveryeasy.Thetwothingsthatthedeveloperneedstoaccomplisharetowritethecodeforthemenuactionandtoaddanentrytothe
plugin.xml.Iwilltakearealworldexampletoillustratetheprocess.Inthisexample,IamwritingapluginthatcausesProtegetodisplayanontologythatisstoredina
databaseformat.IwanttoputthisinthefilemenuofProtege4.1justunderotheritemssuchas"New","Open","OpenRecent"and"OpenfromURL".
Towritethecodeforthemenuplugin,thedevelopermerelyneedstoextendProtegeOWLAction.Thethreemethodsthatthedeveloperneedstowriteareinitialise,dispose
andactionPerformed.Ithinkthatthemeaningofthesethreemethodsisprettyclearandthiscanbeaveryeasytask.
Nowthedeveloperneedstoaddanentrytotheplugin.xml(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/org.protege.example.menu/trunk/plugin.xml)file.Inmycasetheentrylookslikethis:
<extensionid="loadDatabase"
point="org.protege.editor.core.application.EditorKitMenuAction">
<namevalue="LoadDatabaseOntology"/>
<classvalue="org.protege.owlapi.bridge.LoadDatabaseProjectMenu"/>
<toolTipvalue="LoadsontologiesfromadatabaseintoProtege"/>
<pathvalue="org.protege.editor.core.application.menu.FileMenu/SlotAAZ"/>
<editorKitIdvalue="OWLEditorKit"/>
</extension>

The"id"attributeofloadDatabaseissimplyashortidentifierforthepluginthatisnotseenbytheuser.The"point"attributeindicatesthatthepluginbeingdeclaredhereis
amenuplugin.The
<classvalue="org.protege.owlapi.bridge.LoadDatabaseProjectMenu"/>

lineindicatestheclassthatimplementstheactionthatthismenuperformsandthe
<editorKitIdvalue="OWLEditorKit"/>

lineindicatesthatthemenuistobeusedinthecontextoftheowleditor.Theonlyotherlineinthisplugin.xml(http://smi
protege/repos/protege/protege4/incubator/v3/org.protege.owlapi.bridge/trunk/plugin.xml)thatisabitmysteriousisthelinethatsays:
<pathvalue="org.protege.editor.core.application.menu.FileMenu/SlotAAZ"/>

Thepurposeofthislineistoindicateexactlywherethemenushouldbeplaced.Thefirstpartofthevalue,
org.protege.editor.core.application.menu.FileMenu

indicatesthattheparentofmy"LoadDatabaseOntology"menuisthefilemenu.Thestringismakingareferencetothefilemenudeclaration
<extension
id="menu.FileMenu"
name="FileMenu"
point="org.protege.editor.core.application.EditorKitMenuAction">
<namevalue="File"/>
<toolTipvalue="Filemenutooltip!"/>
<pathvalue="/SlotAA"/>
<editorKitIdvalue="any"/>
</extension>

fromtheplugin.xml(http://smiprotege/repos/protege/protege4/plugins/org.protege.editor.core.application/trunk/plugin.xml)filefortheorg.protege.editor.core.application
plugin.Thefirstpartofthestring
org.protege.editor.core.application.menu.FileMenu

is
org.protege.editor.core.application

whichistheidentifieroftheplugindeclaringthemenuand"menu.FileMenu"istheidofthepluginfromtheplugin.xmlfile.
ButnowIneedtoexplainthemeaningoftheSlotAAZportionofthepathinmyoriginalmenudeclaration:
<extensionid="loadDatabase"
point="org.protege.editor.core.application.EditorKitMenuAction">
<namevalue="LoadDatabaseOntology"/>
<classvalue="org.protege.owlapi.bridge.LoadDatabaseProjectMenu"/>
<toolTipvalue="LoadsontologiesfromadatabaseintoProtege"/>
<pathvalue="org.protege.editor.core.application.menu.FileMenu/SlotAAZ"/>
<editorKitIdvalue="OWLEditorKit"/>
</extension>

TheSlotAAZstringindicatesexactlywherethe"LoadDatabaseOntology"shouldappearintheFilemenu.Thisstring(SlotAAZ)isparsedasagroup(SlotAA)andan
index(Z).FirstthegroupandtheindexareusedtosortthechildrenoftheFilemenu.Thechildrenaresortedfirstbygroupbutwhentwochildrenhavethesamegroupthey
arethensortedbygroupindex.Inadditiontothis,childrenwiththesamegrouparegroupedtogetherinthemenu.

http://protegewiki.stanford.edu/wiki/PluginAnatomy

6/11

2/11/2016

PluginAnatomyProtegeWiki

Inparticular,ifItrackdownthedeclarationsofthe"New","Open","OpenRecent"and"OpenfromURL"menusIfindthattheyallhaveagroupidentifierofSlotAA.This
iswhytheyappearinthefilemenutogetherfollowedbyaseparatorbar.ByspecifyingthatmymenushouldhaveagroupofSlotAA,IamtellingProtegethatIwantmy
menutobegroupedwiththesemenus.BygivingmymenuanindexofZIamtellingProtegethatIwantmymenutogoattheendofthelist.
ThealgorithmusedbyProtegetodeterminethelocationoftheplugincanbeobservedbyturningonloggingforthemenubuilder.Thiscaneasilybedonebyeditingthe
log4j.xmlintheProtegeinstallationdirectory.Firstmodifythesectionthatsays
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Threshold"value="INFO"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%m%n"/>
</layout>
</appender>

tosay
<appendername="console"class="org.apache.log4j.ConsoleAppender">
<paramname="Threshold"value="INFO"/>
<layoutclass="org.apache.log4j.PatternLayout">
<paramname="ConversionPattern"value="%m%n"/>
</layout>
</appender>

Thisallowstheconsoletoshowdebugmessages.Thenaddthelines
<categoryname="org.protege.editor.core.ui.menu">

<priorityvalue="debug"/>
</category>

ThiswillcauseProtegetogeneratesomewhatverboselogstotheconsole(theselogsalsoshowupinalogfilein${homedirectory}/.Protege/logs/protege###.log).The
relevantlinesformymenupluginareasfollows.First
Parsed:[Menu:LoadDatabaseOntology<SlotAA,Z>]parentId=org.protege.editor.core.application.menu.FileMenu

indicatesthatProtegewasabletoparsethepathformymenupluginanddeterminethattheidoftheparentis
org.protege.editor.core.application.menu.FileMenu

thegroupisSlotAAandthegroupindexisZ.Nextweseetheline
[Menu:File<SlotA,A>]parentof[Menu:LoadDatabaseOntology<SlotAA,Z>]

whichindicatesthatProtegewassuccessfullyabletofindadeclaredmenuwiththerightidtobetheparentofmymenu.ThislinealsoindicatesthatProtegesuccessfully
decipheredthegroup(SlotAA)andtheindex(Z).Finallytherearethelines:
Adding[Menu:File<SlotA,A>]tomenubar
GivingFilethechild[Menu:New...<SlotAA,E>]
GivingFilethechild[Menu:Open...<SlotAA,F>]
GivingFilethechild[Menu:Openrecent<SlotAA,G>]
GivingFilethechild[Menu:OpenfromURL...<SlotAA,G>]
GivingFilethechild[Menu:LoadDatabaseOntology<SlotAA,Z>]
GivingFilethechild[Menu:Save<SlotAB,A>]
GivingFilethechild[Menu:Saveas...<SlotAB,B>]
GivingFilethechild[Menu:Gatherontologies...<SlotAB,C>]
GivingFilethechild[Menu:Exportinferredaxiomsasontology...<SlotAB,D>]
GivingFilethechild[Menu:Ontologylibraries...<SlotD,A>]
GivingFilethechild[Menu:Loadedontologysources...<SlotD,B>]
GivingFilethechild[Menu:Checkforplugins...<SlotP,A>]
GivingFilethechild[Menu:Close<SlotY,M>]

thatindicatethattheFilemenuwassuccessfullypopulated.

UsingaReasoner
Usuallywhenapluginwantstouseareasoner,thepluginshouldusethereasonerthatisinitializedandusedbyProtege.ThisreasonercouldbetheFaCT++,HermiT,Pellet
orotherreasonersandisselectedandinitializedattheusersrequest.Toexplainhowthisworkswewillexplainhowthefollowing(nottoouseful)codefromamenuplugin
works.
publicvoidactionPerformed(ActionEvente){
OWLClasslastSelectedClass=getOWLWorkspace().getOWLSelectionModel().getLastSelectedClass();
if(lastSelectedClass!=null){
OWLReasonerManagerreasonerManager=getOWLModelManager().getOWLReasonerManager();
ReasonerUtilities.warnUserIfReasonerIsNotConfigured(getOWLWorkspace(),reasonerManager);
if(reasonerManager.getReasonerStatus()==ReasonerStatus.INITIALIZED){
OWLReasonerreasoner=reasonerManager.getCurrentReasoner();
Set<OWLClass>subClasses=reasoner.getSubClasses(lastSelectedClass,true).getFlattened();
if(!subClasses.isEmpty()){
LOGGER.info("Inferredsubclassesof"+getOWLModelManager().getRendering(lastSelectedClass)+"are:");
for(OWLClasssubClass:subClasses){
LOGGER.info("\t"+getOWLModelManager().getRendering(subClass));
}
}
else{
LOGGER.info(getOWLModelManager().getRendering(lastSelectedClass)+"hasnoinferredsubclasses.");
}
}
}
}

Thiscodecreatesanactionthatwheninvokedwillprintsomemessagesaboutinferredsubclassestothelog.ThefirstthingtonoticeisthattheOWLReasonerManageris
thecentralclassforaccessingtheProtegereasoneranditcanbeobtainedfromtheOWLModelManager.Thisclasscanbeusedtodeterminethestatusofthereasoner,get
thecurrentProtegereasonerorgetareasonerfactoryforcreatingnewinstancesofaProtegereasoner.
Oncethereasonermanagerisobtainedcodeaboveinformstheuserifthereasonerisnotinitializedorisininconsistentstate.Thiswarninghasbeenincludedasastandard
Protegeutilitysothattheuserwillgetaconsistentmessagewhenthereasonerisnotreadyforinference.ThisistheapproachtakenbytheDLQuerypluginforinstance
becauseitdoesnotmakesensetousetheDLQuerypluginifthereasonerisnotinitialized.Howeveranalternativeapproachistoquietlycheckthestatusofthereasonerand
onlyusethereasonerifitisinagoodenoughstate.Thisisthestrategytakenbythecodethatdisplaysinferencessuchastheinferredsuperclassesandtheconsistencyof
classesandpropertiesastheusernavigatesthroughtheProtegeinterface.
ThenextthingthathappensisthatthecodechecksthestatusofthecurrentreasonerwiththecallreasonerManager.getReasonerStatus().ThiscallreturnsaReasonerStatus
enumerationwhichcurrentlycantakeonthefollowingvalues:
NO_REASONER_FACTORY_CHOSEN:theuserhasnotyetselectedatypeofreasoner.
REASONER_NOT_INITIALIZED:theuserhasselectedwhattypeofreasonerhewantsbuthasnotinitializedityet.
INITIALIZATION_IN_PROGRESS:thereasonerisintheprocessofbeinginitialized.Pluginsshouldnotseethisstate.
INITIALIZED:thereasonerisreadyforuse.
INCONSISTENT:thereasonerwasinitializedbuttheontologyisinconsistent.Inthisstate,reasonersarenotusable.
OUT_OF_SYNC:thereasonerisreadybutitisnotuptodatewiththelatestchangesintheontology.Thereasonerisusableinthisstatebutitmayproduce
misleadingresults.Itcanbebroughtuptodatewithareasoner.flush()call.
http://protegewiki.stanford.edu/wiki/PluginAnatomy

7/11

2/11/2016

PluginAnatomyProtegeWiki

FinallythecodeaboveobtainstheProtegereasoner(whichimplementstheOWLapiOWLReasonerinterface)andusesOWLapicallstoobtaininformation.
Insomecasestheabovestrategyisnotsufficient.Forexample,theexplanationpluginsneedtocreatetheirownreasonersandsotheyneedareasonerfactory.Inthiscase
theplugincanmakethecall:
reasonerManager.getCurrentReasonerFactory().getReasonerFactory()

toobtainthereasonerfactory(aninstanceoftheOWLapiinterfaceOWLReasonerFactory).

AdvancedTopics
AddingNewPluginTypes
WorkinProgress
OneoftheadvantagesofusingtheOSGi/Eclipseframeworkisthatitnaturallyallowsdeveloperstodefinetheirownplugintypes.Forexample,theSWRLtab,being
writtenbyMartinO'Connor,delegatestheworkofexecutingtheSWRLrulestoaruleengineplugin.Itisanticipatedthattherewillbetworuleenginepluginsthatareare
compatiblewiththeSWRLtab.OneofthesepluginswillbebasedontheJessruleengineandtheotherpluginwillbebasedontheDROOLSruleengine.
WewillillustratehowthisisdonewithtwoProtegebundles.Thesourcesforthesebundlescanbefound
http://smiprotege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/consumer

and
http://smiprotege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/producer

Bothbundlescanbequicklyinstalledthroughtheincludedantscripts.
Theconsumerbundlebehavesasfollows.ItaddsamenuitemtoarunningProtegeenvironment.Thismenuisfoundatthebottomoftheeditmenu.Whentheuserclickson
thismenuitem,theconsumerbundleperformsthefollowingactions:
1.itlooksforallcustom_extension_pointpluginsintherunningProtegeenvironment,
2.itinstantiateseachpluginfoundandfinally
3.itcallsthedoSomething()methodonthatplugininstance.
Thisbehaviorisprovidedthroughtheinteractionoffourcomponents:
theconsumercodethatisresponsibleforloopingthroughasetofpluginsandinvokingthem.
thepluginloaderthatisresponsibleforcalculatingandreturningasetofpluginsthatmatchaspecifiction.
thepluginthatisajavaencodingofdataencodedinplugin.xmlfilesprovidedbythebundles.
theplugininstancethatisaninstantiationofapluginthatdoestheactualworkoftheplugin.
ThePluginConsumer
ThePluginconsumeressentiallyusesthepluginloader(describedbelow)toloopthroughaseriesofpluginsandinstantiateandinvokethem.Thecodethatdoesthiswork
canbefoundintheMyPluginConsumer(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/consumer/src/org/protege/example/extension/point/MyPluginConsumer.java)classand
lookslikethefollowing:
publicvoidactionPerformed(ActionEvente){
MyPluginLoaderloader=newMyPluginLoader(getOWLModelManager());
for(MyPluginplugin:loader.getPlugins()){
try{
MyPluginInstancei=plugin.newInstance();
i.doSomething();
}
catch(Exceptionex){
ProtegeApplication.getErrorLog().logError(ex);
}
}
}

Thisisatypicalexampleofhowapluginconsumerwillwork.Itusesapluginloadertofindasetofpluginsthataretheninstantiated(plugin.newInstance())andthen
invoked(i.doSomething()).Forthemostpart,thepluginconsumerdoesnothavetoworrytoomuchaboutthedetailsoftheProtegeplugininfrastructure.Thelogicofthe
Pluginconsumerisdefinedbythetaskathand.
ThePluginLoader
Thepluginloader(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/consumer/src/org/protege/example/extension/point/MyPluginLoader.java)is
responsibleforsearchingforpluginsofthecustom_extension_pointtype.ThepluginloaderextendstheAbstractPluginLoaderclasswhichhandlesmostofthelogicof
creatingandfindingplugins.Minimally,allthedeveloperneedstodotoimplementthepluginloaderistoimplementaconstructorandacreateinstancemethod.The
constructorlookslikethis:
publicMyPluginLoader(OWLModelManagerowlModelManager){
super(MyPlugin.CONSUMER_ID,MyPlugin.ID);
this.owlModelManager=owlModelManager;
}

andthisistypical.ThesignificanceofthetwoargumentstothesuperconstructorwillbeexplainedwhenIdescribethePluginimplementation.Essentiallytheydefine
whichtypeofpluginisbeingsearchedforbythisloader.Inaddition,theconstructorforthispluginloadertakesanowlModelManagerargumentsothathecanpassthis
argumenttotheconstructorfortheplugins.ThecreateInstancemethodthenisresponsibleforconstructingtheplugin:
protectedMyPlugincreateInstance(IExtensionextension){
returnnewMyPlugin(owlModelManager,extension);
}

InadditionthereisagetExtensionMatchermethodthatcanbeusedtorestrictthesetofpluginsthatarereturnedbythispluginloader.Generallyitisnotnecessaryto
implementthegetExtensionMatcherinterface.
ThePlugin
Essentiallytheplugin(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/consumer/src/org/protege/example/extension/point/MyPlugin.java)isaPOJO
representingadeclarationofaplugininaplugin.xmlfile.Tounderstandthisweneedtolookatthetwodeclarationsintwoseparateplugin.xmlfiles.Thefirstdeclarationis
foundinthebundlefortheconsumerplugin.Thisdeclarationrepresentsarequestforaparticulartypeofservice.Inourcasethedeclaration(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/consumer/plugin.xml)lookslikethis:
<extensionpointid="custom_extension_point"
name="CustomExtensionPoint"
schema="schema/custom_extension_point.exsd"/>

http://protegewiki.stanford.edu/wiki/PluginAnatomy

8/11

2/11/2016

PluginAnatomyProtegeWiki

Thisdeclarationdefines
theidentifieroftheplugintype,custom_extension_point,whichisthenamebywhichplugindevelopersrefertothisplugintype,Thisstringcorrespondstothe
MyPlugin.IDthatwepassedtotheAbstractPluginLoaderconstructorabove.Notethatitispossiblefordifferentbundlestodeclareanextensionpoint
theuserfriendlynameoftheplugintypeand
apointertothexmlschemafortheplugintype.
Ibelievethatthelastitem,theschema(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/consumer/schema/custom_extension_point.exsd),isnotmandatorybutitisextremely
usefulfordevelopersanditiscreatednaturallywhenpluginsaredevelopedusingtheeclipseIDE.
Thepluginproducerprovidedadeclaration(http://smiprotege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/producer/plugin.xml)forhis
extensionthatmatchestheextensionpointdeclarationabove.Inourexampletheextensiondeclarationlookslikethis:
<extensionid="SimpleImplementation"

point="org.protege.example.extension.point.custom_extension_point">
<classvalue="org.protege.example.extension.PluginImplementation"/>
<typevalue="LoggerType"/>
</extension>

Thepluginclass,MyPlugin(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/consumer/src/org/protege/example/extension/point/MyPlugin.java),extendsthe
AbstractProtegePluginclass.TheAbstractProtegePluginclassprovidesmanyutilitiesthatmakeiteasytowritethepluginclass.Inparticular,togetthe"type"fieldthe
MyPluginclassprovidesanaccessor:
/**
*getsthedeclaredtypefieldfortheplugin
*/
publicStringgetType(){
returngetPluginProperty(TYPE_PARAM,"nulltype");
}

Inaddition,theAbstractProtegePluginclassdoesthetrickyaspectsofinstantiatingthepluginleavingonlythetaskofinitializingtheinstantiatedplugintotheMyPlugin
class:
/**
*Createsaninstanceoftheplugin.Itisexpectedthat
*thisinstancewillbe"setup",buttheinstance's
*initialisemethodwillnothavebeencalledintheinstantiation
*process.
*/
publicMyPluginInstancenewInstance()throwsClassNotFoundException,IllegalAccessException,
InstantiationException{

MyPluginInstancempi=super.newInstance();
mpi.setup(modelManager,getType());
returnmpi;
}

ThePluginInstance
Theplugininstanceclass(http://smi
protege.stanford.edu/repos/protege/protege4/misc/examples/custom.extension/trunk/consumer/src/org/protege/example/extension/point/api/MyPluginInstance.java)is
responsibleforperformingwhatevertaskitisthatthepluginissupposedtoperform.InourcasetheplugininstancewillimplementthedoSomething()method.Thisclass
mustimplementtheProtegePluginInstanceinterfacethoughitisnotclearthatthisisreallyneededanymore.TheProtegePluginInstanceinterfacehasonlyonemethod,
initialise(),butmanyplugins,suchastheoneinthisexample,havetheirowninitailizationmethodsthatarecalledbythePluginLoader.

Frames,FrameSections,andRows
InProgress
ItisnotclearthatthisneedstobeherebutthisisanextremelycentralProtegeconcept.IngeneralplugindeveloperswillnotneedtobuildcustomFramelistsandcan
simplyusethetoplevelOWLFrameListconcepts.
MostofthediscussionwillfocusonasmallerandsmallersectionofthethefollowingProtege4.1screen.ThisdiagramshowsthestandardProtege4.1classestabasit
displayssomeinformationabouttheselectedclasswhichistheCountryclassinthepizzaontology.

http://protegewiki.stanford.edu/wiki/PluginAnatomy

9/11

2/11/2016

PluginAnatomyProtegeWiki

FrameListsandFrames
ThediagrambelowshowsaFrameListshowingadescriptionoftheCountryclass.TheOWLFrameLististheswingobjectthatisresponsiblefordisplayingsomeobject
calledtherootobjectfortheOWLFrameList.Inthiscase,therootobjectforthisframelististheCountryOWLclass.Frequentlytherootobjectoftheforaframelistisan
OWLentitybutthisisnotrequired.TheconstructorfortheOWLFrameListobjecttakesanOWLFrameobjectwhichmanagesthecontentmodeloftheOWLFrameList.
TheassociatedOWLFrameobjectalsohasarootobjectandinthiscasetherootobjectistheCountryclass.
Whileitmaynotbevisuallyimmediatelyapparent,theinformationbeingdisplayedisactuallyarenditionofalistofaxioms.Thusforinstance,theclassexpression
representedinthesectionunderneathEquivalentClassesrepresentstheaxiom
CountrySubClassOfDomainConceptand{America,England,France,Germany,Italy}.

SimilarlythefirstindividualdisplayedunderMembersrepresentstheaxiom
AmericaTypeCountry.

ThefactthatthesearenotdisplayedsimplyastheassociatedaxiomsisankeypartofthepurposeoftheOWLFrameList.ThetaskoftheOWLFrameListbelowisto
describetheCountryclass.ForauseritmakessensethatintheMemberssectionofthatOWLFrameListhewouldseealistoftheindividualsinthatclass.Itwouldmake
lesssensetotheuserifasetofaxiomswasdisplayedthere.

FrameSections
OWLFramesaregroupedintoaseriesofsectionseachofwhichshowsaparticulartypeofaxioms.Inthediagrambelowwehaveaframesectionthatisrenderingalistof
classassertionaxioms.

http://protegewiki.stanford.edu/wiki/PluginAnatomy

10/11

2/11/2016

PluginAnatomyProtegeWiki

FrameSectionRows

Glossary
TherearesometermsthatcomeupnaturallyinthediscussionofProtege4plugindevelopmentthatrequireabitofexplanation.TheProtege4pluginmechanismhasthree
layersandthetermsusedtodescribepluginsisslightlydifferentateachoftheselayers:
ExtensionPointistheeclipsetermforwhatProtegefolkoftencallaplugin.
OSGi(http://www.osgi.org/Main/HomePage)isthebottomlayeroftheProtegepluginarchitecture.Itisapowerfulindustrystandardframeworkwhichprovides
modularityandservicesbeyondthatprovidedbytheJavaspecifications.InOSGi,thetermOSGibundleisusedtorepresentaselfcontainedunitofcodethatcanbe
introducedintotheOSGiframeworkandwhichwillimportandexportclassesandresourcesinacontrolledway.
AnOSGiBundleiscollectionofsoftwaregroupedintoasinglejarfile.WhenthissoftwarerunsintheOSGienvironment,itrunsinaprotectedspacewhereitcan
defineexactlywhatjavaclassesfromthesurroundingenvironmentareneededandwhatjavaclassesareincompatiblewithitsoperation.Bundleshavenames,version
numbers,developercontactinformationandactivationentrypoints.
APluginisadeclaredservicethatimplementssomefunctionalityofusetotheProtegeplatform.TheProtegePluginmechanismisbasedontheEclipseplugin
mechanismwherepluginsaredeclaredinafilecalledplugin.xml.
TheEclipseRichClientPlatform(http://wiki.eclipse.org/index.php/Rich_Client_Platform)isanenvironmentbuiltontopofOSGiwhichprovidesadditional
featurestoeasethebuildingofa"Rich"client.Protege4onlyusessomeofthefeaturesofthisrichclientplatform.Inparticular,Protege4doesnotuseSWTand
manyofthegraphicalrelatedcapabilities.ButProtege4doesusethedeclarativeplugincapabilitiesprovidedbyeclipse.ItisherethatsomeofthepoweroftheOSGi
platformbecomesmanifest,becausewehavebeenabletouseonlythosebundlesfromtheeclipseRichClientplatformthatweneed.Inthissetting,OSGibundles
createdaccordingtocertainconventionsbecomeEclipsePlugins.
TheProtege4PluginlayerprovidessomeadditionalconveniencemethodsovertheEclipsePluginframework.CertaineclipsepluginsthatextendProtege4
capabilitiesarecalledProtege4plugins.
Retrievedfrom"http://protegewiki.stanford.edu/index.php?title=PluginAnatomy&oldid=12200"
ThispagewaslastmodifiedonSeptember1,2013,at06:34.

http://protegewiki.stanford.edu/wiki/PluginAnatomy

11/11

You might also like