root/PSi/PNK2.2/doc/pnk-guide/index.html @ 2e0a7cb1
2e0a7cb1 | Sylvain L. Sauvage | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<HTML>
|
|||
<HEAD>
|
|||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
|||
<TITLE>PNK User's Manual</TITLE>
|
|||
<META NAME="GENERATOR" CONTENT="StarOffice/5.2 (Linux)">
|
|||
<META NAME="CREATED" CONTENT="20010908;12154100">
|
|||
<META NAME="CHANGEDBY" CONTENT="Alexander Gruenewald">
|
|||
<META NAME="CHANGED" CONTENT="20010908;12364400">
|
|||
</HEAD>
|
|||
<BODY BGCOLOR="#ffffff">
|
|||
<P>The Petri Net Kernel (PNK) version 2.0 provides an infrastrucure
|
|||
for building Petri net tools.
|
|||
</P>
|
|||
<P STYLE="margin-bottom: 0cm">Copyright (C) 2001 Petri Net Kernel
|
|||
Team (Humboldt-University Berlin, Germany)
|
|||
</P>
|
|||
<ADDRESS STYLE="margin-bottom: 0.5cm"><A HREF="mailto:pnk@informatik.hu-berlin.de">pnk@informatik.hu-berlin.de</A></ADDRESS>
|
|||
<H3>PNK User's Manual</H3>
|
|||
<HR>
|
|||
<H3>Table of Contents</H3>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#License Agreement">License Agreement
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Quick Start">Quick Start</A>
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Quick Start">Download
|
|||
and Run</A>
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#First steps - Open, Edit and Save Nets">First
|
|||
steps - Open, Edit and Save Nets</A>
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Start a first Simulator Session">Start
|
|||
a first Simulator Session</A>
|
|||
</P>
|
|||
</UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Some Basics">Some Basics
|
|||
</A>
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#The Kernel">The Kernel</A>
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#The ApplicationControl">The
|
|||
ApplicationControl</A>
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#The Editor">The Editor</A>
|
|||
</P>
|
|||
</UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Write Applications">Write
|
|||
Applications</A>
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Example Simulator">Example
|
|||
Simulator</A>
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#The FiringRule interface">The
|
|||
FiringRule Interface</A>
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Communication between Applications">Communication
|
|||
between Applications</A>
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Application with Menu">Application
|
|||
with Menu</A>
|
|||
</P>
|
|||
<LI><P><A HREF="#Load Applications">Load Applications</A>
|
|||
</P>
|
|||
</UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm"><A HREF="#Write Nettypes">Write
|
|||
Nettypes</A>
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P><A HREF="#Marking">Marking</A>
|
|||
</P>
|
|||
<LI><P><A HREF="#Inscription">Inscription</A>
|
|||
</P>
|
|||
<LI><P><A HREF="#FiringRule">FiringRule</A>
|
|||
</P>
|
|||
</UL>
|
|||
</UL>
|
|||
<HR>
|
|||
<A NAME="Quick Start"></A>
|
|||
<H3>License Agreement</H3>
|
|||
<P>The PNK version 2.0 is free software; you can redistribute it
|
|||
and/or modify it under the terms of the GNU Library General Public
|
|||
License (see file LICENSE.GNU-LGPL) as published by the Free Software
|
|||
Foundation; version 2 of the license. (Note, that some PNK
|
|||
applications are developed under GNU General Public License---see
|
|||
file <A HREF="http://www.gnu.org/copyleft/gpl.html">http://www.gnu.org/copyleft/gpl.html</A>
|
|||
) The PNK is distributed in the hope that it will be useful, but
|
|||
WITHOUT ANY WARRANTY.</P>
|
|||
<P><A NAME="Quick Start"></A>You are NOT ALLOWED to CHANGE THE
|
|||
ORIGINAL COPYRIGHT NOTICE. See the GNU Library General Public License
|
|||
for more details. You should have received a copy of the GNU Library
|
|||
General Public License along with the PNK; if not see
|
|||
http://www.gnu.org/. An application using the Petri Net Kernel MUST
|
|||
GIVE NOTICE OF THIS USE. Please contact pnk@informatik.hu-berlin.de
|
|||
to notify this application.
|
|||
</P>
|
|||
<H3>Quick Start</H3>
|
|||
<HR>
|
|||
<P>This is just a crash course to get the Petrinet Kernel running. It
|
|||
should give you an overview how to use the Petrinet Kernel. I'm
|
|||
leaving out some important details which will be added soon ...
|
|||
</P>
|
|||
<P>NOTE: It is important that you have installed the jdk1.2.2 to use
|
|||
the Petrinet Kernel. Otherwise download it from <A HREF="http://java.sun.com/">java.sun.com</A>.
|
|||
If you don't know which jdk version is installed on your system, you
|
|||
may check this by calling the Java interpreter's <CODE>-version</CODE>
|
|||
option.
|
|||
</P>
|
|||
<P><CODE>java -version</CODE>
|
|||
</P>
|
|||
<H4><A NAME="Download and Run"></A>Download and Run</H4>
|
|||
<P>Download the latest <A HREF="http://SP-berlin2001.glia.mdc-berlin.de/">PNK2alpha.jar</A>
|
|||
file. Extract the archive on the command line by typing
|
|||
</P>
|
|||
<P><CODE>jar xvf PNK2alpha.jar</CODE>
|
|||
</P>
|
|||
<P>This creates a new directory <EM>PNK2/</EM> containing the source
|
|||
and class files of the Petrinet Kernel. Now you may change to <EM>PNK2/</EM>
|
|||
directory
|
|||
</P>
|
|||
<P><CODE>cd PNK2</CODE>
|
|||
</P>
|
|||
<P>and take a look at it's contents. You should find something like
|
|||
this ...
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm">jaxp.jar - api for reading and
|
|||
writing <EM>xml</EM> files
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">crimson.jar - api for reading and
|
|||
writing <EM>xml</EM> files
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">PNK2.jar - archive of the Petrinet
|
|||
Kernel's class files
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">PNK2sources.jar - archive of the
|
|||
Petrinet Kernel's source files
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">Makefile - with this you may
|
|||
compile sources by hand
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">sampleNets - contains some saved
|
|||
netexamples
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">netTypeSpecifications - contains
|
|||
examples for a net's specification
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">toolSpecification - contains some
|
|||
toolspecification examples
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">icons - icons used by applications
|
|||
</P>
|
|||
<LI><P>license
|
|||
</P>
|
|||
</UL>
|
|||
<P>Then start up Petrinet Kernel using the <CODE>-jar</CODE> option
|
|||
of the java interpreter.
|
|||
</P>
|
|||
<P><CODE>java -jar PNK2.jar</CODE>
|
|||
</P>
|
|||
<P>You may also compile sources by hand. Therefore you possibly have
|
|||
to extract a source file archive.
|
|||
</P>
|
|||
<P><CODE>jar xvf PNK2sources.jar</CODE>
|
|||
</P>
|
|||
<P>This command installs a directory tree of source files. Now take
|
|||
notice of the <EM>makefile</EM> in the <EM>PNK2/</EM> root directory.
|
|||
Modify it to your requirements and enter
|
|||
</P>
|
|||
<P><CODE>make run</CODE>
|
|||
</P>
|
|||
<P>This command should compile all files and run the Petrinet Kernel.
|
|||
If it does not, please check the path to your java2 interpreter and
|
|||
java2 compiler. You may edit the path in the headline of the
|
|||
<EM>makefile</EM>. Verify also the correctness of the CLASSPATH
|
|||
variable. It should at least point to the <EM>crimson.jar</EM> and
|
|||
<EM>jaxp.jar</EM> archives distributed with the <EM>pnk.jar</EM>
|
|||
archive. These two file archives are necessary for loading and
|
|||
writing xml and pnml files.
|
|||
</P>
|
|||
<P>At first change into the directory where you placed the downloaded
|
|||
<EM>PNK2alpha.jar</EM> file. Extract the file and examine the
|
|||
contents of the new directory. Finally run the Petrinet Kernel using
|
|||
the <CODE>-jar</CODE> option supported by the java2 interpreter.
|
|||
</P>
|
|||
<P>If the makefile doesn't work you may generally start the Petrinet
|
|||
Kernel by typing a commandline like this:
|
|||
</P>
|
|||
<P><CODE>java -classpath .:jaxp.jar:crimson.jar
|
|||
de.huberlin.informatik.pnk.appControl.ApplicationControl</CODE>
|
|||
</P>
|
|||
<P>In this case it is important that you are currently in the root
|
|||
directory of the Petrinet Kernel. First steps - Open, Edit and Save
|
|||
Nets
|
|||
</P>
|
|||
<A NAME="First steps - Open, Edit and Save Nets"></A>
|
|||
<H4>First steps - Open, Edit and Save Nets</H4>
|
|||
<P>Now I will give you a short tutorial how you can play around with
|
|||
the Petrinet Kernel. In this section I tell you how you may open or
|
|||
edit nets and how you may invoke applications to work on your net.
|
|||
When launching the Petrinet Kernel the ApplicationControl's window
|
|||
should appear.
|
|||
</P>
|
|||
<P><IMG SRC="ApplicationControlFrame.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=450 HEIGHT=85 BORDER=0>
|
|||
</P>
|
|||
<P>In the ApplicationControl's menubar you find a <EM>File</EM> menu
|
|||
for opening existing nets, creating new nets and saving nets. There
|
|||
should also be a <EM>Net</EM> menu to launch applications related to
|
|||
a specific net and switch between them. At first you have to choose
|
|||
your nettype. You may open the <EM>File</EM> menu. If you select the
|
|||
<EM>File -> new Net</EM> menuentry a submenu with a list of
|
|||
different nettypes appears. Click on one of these menuitems. You can
|
|||
also select the <EM>File -> Open</EM> menuentry to open an
|
|||
existing net. Some interesting netexamples are stored in the
|
|||
<CODE>sampleNets/</CODE> directory.
|
|||
</P>
|
|||
<P><IMG SRC="ApplicationControlOpenDialog.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=451 HEIGHT=254 BORDER=0>
|
|||
</P>
|
|||
<P>By default a editor start's to display the net. Everytime you
|
|||
invoke an application it's menu is shown in the ApplicationControl's
|
|||
menubar. So now you should find there the editor's menu.
|
|||
Alternatively you may use the popupmenu of the editor.
|
|||
</P>
|
|||
<P><IMG SRC="EditorFrame.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=603 HEIGHT=379 BORDER=0>
|
|||
</P>
|
|||
<P>Probable you ask: 'How can I add objects like places, transitions
|
|||
and arcs to the net?' In the editor's menu you select the <EM>Place</EM>
|
|||
checkbox or the <EM>Transition</EM> checkbox. Then click on an open
|
|||
editorpage. Every mouseclick should create a new object. Then choose
|
|||
the <EM>Arc</EM> checkbox and mouseclick on a place. The place should
|
|||
change it's color indicating that it is selected as an arc's
|
|||
initialnode. Now mouseclick a transition and a new arc appears. You
|
|||
may want to drag around some places and transitions to make your net
|
|||
look lovely. You achieve this by mouseclicking in an object and hold
|
|||
the mousebutton pressed while moving your mouse. After this you
|
|||
usually want edit the extensions of some objects. For example set the
|
|||
<CODE>name</CODE> and <CODE>marking</CODE> of places, the
|
|||
<CODE>inscriptions</CODE> of several arcs or the <CODE>guards</CODE>
|
|||
of transition. Which of these extensions exists depends on the
|
|||
nettype. To edit an extension you choose the <EM>Edit</EM> checkbox
|
|||
in editor's popupmenu. Now a mouseclick on a place, transition or arc
|
|||
will open a dialog frame where you may set new values for the objects
|
|||
extensions.
|
|||
</P>
|
|||
<P><IMG SRC="EditorFrameWithMenu.png" NAME="Grafik4" ALIGN=BOTTOM WIDTH=531 HEIGHT=355 BORDER=0>
|
|||
</P>
|
|||
<P><A NAME="Start a first Simulator Session"></A>You can open a
|
|||
second page using the editor's menu in the ApplicationControl's
|
|||
menubar. If you enable the <EM>join</EM> checkbox you may join two
|
|||
different nodes as one node. That's the way you merge the pages.
|
|||
Therefore you click in a place and it should change it's color than
|
|||
click into another place. Now these places represent both the same
|
|||
place of the net. You can undo this with the help of the <EM>split</EM>
|
|||
operation. Then it is recommended that you save your net with the
|
|||
<EM>File -> save</EM> or <EM>File -> save as</EM> menu and
|
|||
choose ApplicationControl's <EM>Net</EM> menu to start a further
|
|||
application for example a simulator.
|
|||
</P>
|
|||
<H4>Start a first Simulator Session</H4>
|
|||
<P><A NAME="Some Basics"></A>Choose <EM>Net -> Start Application
|
|||
-> Simulator</EM>. This creates a new instance of the simulator.
|
|||
Now the simulator's menu should appear in the ApplicationControl's
|
|||
menubar. Please pay attention to the fact that some applications (for
|
|||
example the simulator) are not automatically launched when they were
|
|||
invoked. To run the simulator choose the <EM>Simulator -> Start</EM>
|
|||
menu from ApplicationControl's menubar. You should now see a dialog
|
|||
frame with a <EM>CANCEL</EM> button, pushing this button will abort
|
|||
the simulator application. If there is any concessioned transition in
|
|||
the net the simulator will emphasize it in the editor. You may fire a
|
|||
concessioned transition by mouseclicking into it. Continue these
|
|||
steps until you are tired or there is no concessioned transition
|
|||
anymore. In the first case press the <EM>CANCEL</EM> button in the
|
|||
simulator's dialog frame. (It is recommended that you don't choose
|
|||
<EM>Simulator -> Stop</EM> from ApplicationControl's menubar,
|
|||
because it's not yet correctly implemented.) In the last case the
|
|||
simulator stops automatically.
|
|||
</P>
|
|||
<H3>Some Basics</H3>
|
|||
<HR>
|
|||
<P>Now I want to introduce you in some details so that you are able
|
|||
to develop your own petrinet application using the Petrinet Kernel.
|
|||
The Petrinet Kernel's sources are a bunch of packages. These are ...
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.kernel
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.kernel.base
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.app
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.app.base
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.appControl
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.appControl.base
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.netElementExtensions
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.netElementExtensions.base
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">de.huberlin.informatik.pnk.editor
|
|||
</P>
|
|||
<LI><P>de.huberlin.informatik.pnk.exceptions
|
|||
</P>
|
|||
</UL>
|
|||
<P>The idea of the Petrinet Kernel project is to make a petrinet data
|
|||
structure available for developers and scientists. We decided to add
|
|||
an editor to the project to remove this task from developers. And
|
|||
finally we created the ApplicationControl with should make it easy to
|
|||
compose nets and applications to one large application.
|
|||
</P>
|
|||
<P><A NAME="The Kernel"></A>In the following I will say something
|
|||
about the mainpackages and mainclasses.
|
|||
</P>
|
|||
<H4>The Kernel</H4>
|
|||
<P>The <CODE>de.huberlin.informatik.pnk.kernel</CODE>'s package
|
|||
contains especially the following important classes:
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm">Net
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">Arc
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">Place
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">Transition
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">Extension
|
|||
</P>
|
|||
<LI><P>Specification
|
|||
</P>
|
|||
</UL>
|
|||
<P>A petrinet is a bipartitioned, directed graph with nodes called
|
|||
places and transitions.
|
|||
</P>
|
|||
<P>For the beginning I list the methods of these classes and try to
|
|||
explain their meaning. Then I will discuss their use by an example.
|
|||
</P>
|
|||
<P>The <CODE>Net</CODE> class describes a petrinet. It has methods to
|
|||
access their arcs, places and transitions. Or you may ask a net for
|
|||
it's <CODE>FiringRule</CODE> object that describes when a transition
|
|||
is concessioned and how you does it fire. How do you may profite from
|
|||
these methods you will see in the <EM>Example Simulator</EM> chapter.
|
|||
</P>
|
|||
<PRE>
|
|||
public final class Net extends Graph {
|
|||
public Vector getArcs()
|
|||
public Vector getPlaces()
|
|||
public Vector getTransitions()
|
|||
public FiringRule getFiringRule()
|
|||
} // class Net
|
|||
</PRE>
|
|||
<P>
|
|||
The <CODE>Place</CODE> class describes a place of a petrinet. You
|
|||
create a place using the class constructor. The place registers
|
|||
itself in the net which must be passed as a constructor's parameter.
|
|||
You can remove a place by calling it's <CODE>delete()</CODE> method.
|
|||
You may request the current marking and so on ...
|
|||
</P>
|
|||
<PRE>
|
|||
public final class Place extends Node
|
|||
public Place(Net net, String name, Object initiator)
|
|||
public void delete(Object initiator)
|
|||
public Marking getMarking()
|
|||
public void setMarkingAsInitial()
|
|||
} // class Place
|
|||
</PRE>
|
|||
<P>
|
|||
The <CODE>Transition</CODE> class describes a transition of a
|
|||
petrinet. You create a transition using the class constructor. The
|
|||
transition registers itself in the net which must be passed as a
|
|||
constructor's parameter. You delete it using it's <CODE>delete()</CODE>
|
|||
method. You can also request the mode of a transition.
|
|||
</P>
|
|||
<PRE>
|
|||
public final class Transition extends Node {
|
|||
public Transition(Net net, String name, Object initiator)
|
|||
public void delete(Object initiator)
|
|||
public Mode getMode()
|
|||
} // class Transition
|
|||
</PRE>
|
|||
<P>
|
|||
The <CODE>Arc</CODE> class describes an arc of a petrinet. You create
|
|||
a new arc using the class constructor. The arc registers itself in
|
|||
the net passed as constructor parameter. You may ask an arc for it's
|
|||
initialnode, it's targetnode, it's inscription and so on ...
|
|||
</P>
|
|||
<PRE>
|
|||
public class Arc extends Edge {
|
|||
public Arc(Net net, Node source, Node target, Object initiator)
|
|||
public Inscription getInscription()
|
|||
public Place getPlace()
|
|||
public Transition getTransition()
|
|||
/// METHODS INHERITED FROM class Edge:
|
|||
public Node getSource()
|
|||
public Node getTarget()
|
|||
} // class Arc
|
|||
</PRE>
|
|||
<p>
|
|||
<H4>
|
|||
<A NAME="The ApplicationControl"></A>The ApplicationControl</H4>
|
|||
<P>As you already notice the ApplicationControl in the
|
|||
<CODE>de.huberlin.informatik.pnk.appControl</CODE> package plays an
|
|||
very important role. This class manages all nets and applications of
|
|||
the Petrinet Kernel. The ApplicationControl parses some XML files for
|
|||
configuration. These are for example the specification of all
|
|||
nettypes in the <EM>netTypeSpecification</EM> directory or a list of
|
|||
valid applications to each nettype in <EM>toolSpecification.xml</EM>
|
|||
file. Furthermore it is responsible for loading and writing nets as
|
|||
PNML files. It also offers useful interfaces that lets different
|
|||
applications cooperate with each other. Using the main <CODE>main()</CODE>
|
|||
method of the ApplicationControl you launch the Petrinet Kernel on
|
|||
commandline.
|
|||
</P>
|
|||
<P><pre>
|
|||
java -classpath .:crimson.jar:jaxp.jar \
|
|||
de.huberlin.informatik.pnk.appControl.ApplicationControl \
|
|||
toolSpecifications/toolSpecification.xml
|
|||
</pre>
|
|||
</P>
|
|||
<P>Of course you have to specify the classpath correctly. Optional
|
|||
you may give the location of an <EM>toolSpecification.xml</EM> file
|
|||
as argument. If you don't the ApplicationControl uses
|
|||
<EM>toolSpecifications/toolSpecification.xml</EM> as default. With
|
|||
the toolSpecification.xml file you inform the ApplicationControl of
|
|||
known nettypes and applications. The idea is to give you the
|
|||
possibility to compose your own toolsets. This for example could be
|
|||
the content of <EM>toolSpecifications/toolSpecification.xml</EM> :
|
|||
</P>
|
|||
<PRE>
|
|||
< ?xml version="1.0" encoding="UTF-8"? >
|
|||
< !DOCTYPE toolSpecification SYSTEM "toolSpecification.dtd" >
|
|||
< toolSpecification >
|
|||
< !-- Nettypes -- >
|
|||
< nettype id="n1" typeSpecification="file:netTypeSpecifications/simpleHLNet.xml"/ >
|
|||
< nettype id="n2" typeSpecification="file:netTypeSpecifications/dawnNet.xml"/ >
|
|||
< nettype id="n3" typeSpecification="file:netTypeSpecifications/Echo.xml"/ >
|
|||
< !-- Applications -- >
|
|||
< application id="a1" mainClass="de.huberlin.informatik.pnk.editor.Editor" maxinstances="inf" >
|
|||
< allowedNettypes >
|
|||
< ntref ref="n1"/ >
|
|||
< ntref ref="n2"/ >
|
|||
< ntref ref="n3"/ >
|
|||
< /allowedNettypes >
|
|||
< /application >
|
|||
< !-- Input / Output -- >
|
|||
< format id="pnml" ioClass="de.huberlin.informatik.pnk.appControl.PnmlInOut" >
|
|||
< allowedNettypes >
|
|||
< ntref ref="n1"/ >
|
|||
< ntref ref="n2"/ >
|
|||
< /allowedNettypes >
|
|||
< /format >
|
|||
< format id="io" ioClass="de.huberlin.informatik.pnk.appControl.InOut" >
|
|||
< /format >
|
|||
< !-- default settings -- >
|
|||
< standardNettype ref="n1"/ >
|
|||
< standardApplication ref="a1"/ >
|
|||
< standardFormat ref="pnml"/ >
|
|||
< /toolSpecification >
|
|||
</PRE>
|
|||
<P>
|
|||
<A NAME="The Editor"></A>You see that the toolspecificationfile is
|
|||
structured in three parts. The first part declares the nettypes, the
|
|||
second part lists the applications with references to nettypes and
|
|||
the third part defines Input/Output formats (in this case PNML).
|
|||
For each application you may list the allowed nettypes. If you drop
|
|||
the < allowedNettypes > tag, it is supposed that all nettypes
|
|||
are tolerated. If the < allowedNettypes > tag is found
|
|||
but it's empty, it is supposed that no nettype is allowed.
|
|||
</P>
|
|||
<H4>The Editor</H4>
|
|||
<P><A NAME="Write Applications"></A>If you open a net it is by
|
|||
default displayed in an editor. The editor application resists in the
|
|||
<CODE>de.huberlin.informatik.pnk.editor</CODE> package. I presume
|
|||
that you never need to access it directly. To let your application
|
|||
work with an editor it is recommended to use the offered interface
|
|||
<EM>ApplicationNetDialog</EM>. Nevertheless you may look at the
|
|||
editor's implementation to learn how to combine complex applications
|
|||
and the ApplicationControl.
|
|||
</P>
|
|||
<H3>Write Applications</H3>
|
|||
<HR>
|
|||
<P><A NAME="Example Simulator"></A>Now I will give you a short
|
|||
introduction how to write an application by discussing the
|
|||
implementation of a simulator.
|
|||
</P>
|
|||
<H4>Example Simulator</H4>
|
|||
<P>Now let's take a look at the <EM>Simulator</EM> application in the
|
|||
<CODE>de.huberlin.informatik.pnk.app</CODE> package. This example
|
|||
should show how easy it is to write an application.
|
|||
</P>
|
|||
<PRE>
|
|||
package de.huberlin.informatik.pnk.app;
|
|||
import de.huberlin.informatik.pnk.app.base.MetaApplication;
|
|||
import de.huberlin.informatik.pnk.appControl.ApplicationControl;
|
|||
import de.huberlin.informatik.pnk.netElementExtensions.llNet.SimpleRule;
|
|||
/**
|
|||
* Simulator.java
|
|||
*
|
|||
* Created: Wed Jan 24 08:51:50 2001
|
|||
*
|
|||
* @author hohberg
|
|||
* @version
|
|||
*/
|
|||
public class Simulator extends MetaApplication {
|
|||
// this application's name
|
|||
public static String staticAppName = "Simulator";
|
|||
// class constructor
|
|||
public Simulator(ApplicationControl ac) {
|
|||
super(ac);
|
|||
}
|
|||
public void run() {
|
|||
SimpleRule rule =
|
|||
(SimpleRule) net.getExtension("firingRule");
|
|||
rule.simulateWithUserInteraction(this);
|
|||
}
|
|||
} // Simulator
|
|||
</PRE><P>
|
|||
The Simulator extends the <CODE>MetaApplication</CODE> class.
|
|||
</P>
|
|||
<PRE>
|
|||
public class Simulator extends MetaApplication
|
|||
</PRE><P>
|
|||
Every application has to extend this class to inherit important base
|
|||
functionality. The class constructor has to take an
|
|||
<CODE>ApplicationControl</CODE> object as parameter and propagate it
|
|||
with the <CODE>super()</CODE> call to the <CODE>MetaApplication</CODE>'s
|
|||
class constructor.
|
|||
</P>
|
|||
<PRE>
|
|||
public Simulator(ApplicationControl ac) {
|
|||
super(ac);
|
|||
}
|
|||
</PRE><P>
|
|||
The application may define it's name in a static class field
|
|||
<CODE>staticAppName</CODE> so the ApplicationControl can display the
|
|||
application's name in it's menubar.
|
|||
</P>
|
|||
<PRE>
|
|||
public static String staticAppName = "Simulator";
|
|||
</PRE><P>
|
|||
The application then implements a <CODE>run()</CODE> method. This
|
|||
method is called by the ApplicationControl to start the application.
|
|||
</P>
|
|||
<PRE>
|
|||
public void run() {
|
|||
</PRE><P>
|
|||
After this the Simulator requests a net's extension using the <CODE>net</CODE>
|
|||
field inherited from the MetaApplication class.
|
|||
</P>
|
|||
<PRE>
|
|||
SimpleRule rule = (SimpleRule) net.getExtension("firingRule");
|
|||
rule.simulateWithUserInteraction(this);
|
|||
</PRE><H4>
|
|||
<A NAME="The FiringRule interface"></A>The FiringRule interface</H4>
|
|||
<P>The SimpleRule class implements the interface
|
|||
<CODE>de.huberlin.informatik.pnk.netElementExtensions.base.FiringRule</CODE>.
|
|||
This interface defines methods like:
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm">void fire(Vector transitions); //
|
|||
Fires some transitions
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">Vector getAllConcessioned(); //
|
|||
returns a list of concessioned transitions
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">Transition getConcessioned(); //
|
|||
returns only one concessioned transition
|
|||
</P>
|
|||
<LI><P>boolean isConcessioned(Transition t); // checks if a
|
|||
transition is concessioned
|
|||
</P>
|
|||
</UL>
|
|||
<P>The <CODE>SimpleRule</CODE> object is nettype specific and has to
|
|||
be implemented with the nettype. How to create new nettypes will be
|
|||
discussed in a later section. Furthermore the method
|
|||
<CODE>simulateWithUserInteraction(MetaApplication app)</CODE> is
|
|||
declared in the SimpleRule class. It is implemented as:
|
|||
</P>
|
|||
<PRE>
|
|||
public class SimpleRule extends FiringRule {
|
|||
...
|
|||
public void simulateWithUserInteraction(MetaApplication app) {
|
|||
checkContextAndParseExtensions();
|
|||
ApplicationControl ac = app.getApplicationControl();
|
|||
Net net = (Net) getGraph();
|
|||
Vector concessioned = getAllConcessioned( ); //all concessioned transitions
|
|||
if(conc == null || conc.isEmpty())
|
|||
return;
|
|||
Transition transition = (Transition)
|
|||
(new SelectObjectAction(ac, net, app, concessioned)).invokeAction();
|
|||
while(transition != null) {
|
|||
fire(transition);
|
|||
concessioned = getAllConcessioned();
|
|||
if(concessioned == null || concessioned.isEmpty())
|
|||
return;
|
|||
transition = (Transition)
|
|||
(new SelectObjectAction(ac, net, app, concessioned)).invokeAction();
|
|||
}
|
|||
}
|
|||
...
|
|||
} // class SimpleRule
|
|||
</PRE><P>
|
|||
<A NAME="Communication between Applications"></A>The implementation
|
|||
of this simulateWithUserInteraction() method is interesting in many
|
|||
aspects. Especially you see the use of the FiringRule interface.
|
|||
Farther you see how applications communicate with each other.
|
|||
</P>
|
|||
<H4>Communication between applications</H4>
|
|||
<P>For short I want to introduce the Petrinet Kernel's concept of
|
|||
communication between applications. The Editor for example implements
|
|||
the <EM>ApplicationNetDialog</EM> interface in
|
|||
<CODE>de.huberlin.informatik.pnk.app.base</CODE> package. This
|
|||
interface serves a couple of nice methods. With the help of these
|
|||
methods an application may request the editor to emphasize, select or
|
|||
annotate a place, transition or arc.
|
|||
</P>
|
|||
<PRE>
|
|||
package de.huberlin.informatik.pnk.app.base;
|
|||
import de.huberlin.informatik.pnk.kernel.*;
|
|||
import java.util.*;
|
|||
/*
|
|||
* If an application want's to request the editor
|
|||
* to emphasize, annotate or select (one object | some objects),
|
|||
* it may use the methods of this interface.
|
|||
*/
|
|||
public interface ApplicationNetDialog {
|
|||
// The application requests the editor to annotate some objects.
|
|||
public void anotateObjects(Hashtable annotations);
|
|||
// The application requests the editor to emphasize some objects.
|
|||
public void emphasizeObjects(Vector objects);
|
|||
// The application requests the editor to reset all annotations.
|
|||
public void resetAnnotations();
|
|||
// The application requests the editor to unemphasize all objects.
|
|||
public void resetEmphasize();
|
|||
// The application requests the editor to select an object.
|
|||
public Member selectObject(Vector objects);
|
|||
// The application requests the editor to select some objects...
|
|||
public Vector selectObjects(Vector objects);
|
|||
// The application requests the editor to unannotate the objects.
|
|||
public void unAnotateObjects(Vector objects);
|
|||
// The application requests the editor to unEmphasize the objects.
|
|||
public void unEmphasizeObjects(Vector objects);
|
|||
} //interface ApplicationNetDialog
|
|||
</PRE><P>
|
|||
Communication is realized with the help of ActionObjects. The
|
|||
following examples of ActionObjects reside in
|
|||
<CODE>de.huberlin.informatik.pnk.app.base</CODE>
|
|||
</P>
|
|||
<UL>
|
|||
<LI><P STYLE="margin-bottom: 0cm">AnnotateObjectsAction // Requests
|
|||
to annotate object
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">ResetAnnotationsAction //
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">UnAnnotateObjectsAction //
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">SelectObjectAction // Requests to
|
|||
select an object
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">ResetEmphasizeAction //
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">SelectObjectsAction // Requests to
|
|||
select a collection of objects
|
|||
</P>
|
|||
<LI><P STYLE="margin-bottom: 0cm">EmphasizeObjectsAction // Requests
|
|||
to emphasize a collection of objects
|
|||
</P>
|
|||
<LI><P>UnEmphasizeObjectsAction
|
|||
</P>
|
|||
</UL>
|
|||
<P>An application can initialize an ActionObject giving a reference
|
|||
of the ApplicationControl that should find a suitable request
|
|||
executer application and a reference of the net this application
|
|||
currently processes and calls the ActionObject's <CODE>invokeAction()</CODE>
|
|||
method.
|
|||
</P>
|
|||
<PRE>
|
|||
/**
|
|||
* I presume that an MetaApplication 'app' requests the ApplicationControl 'ac'
|
|||
* to instruct another MetaApplication (that implements the 'ApplicationNetDialog' interface)
|
|||
* to select a transition from the java.util.Vector 'concessioned'.
|
|||
*/
|
|||
Net net; // net the transitions belong to
|
|||
Vector concessioned; // one of these transitions should be selected
|
|||
MetaApplication app; // application that initiates the request
|
|||
ApplicationControl ac; // applicationcontrol that routes the request
|
|||
Transition transition = (Transition)
|
|||
(new SelectObjectAction(ac, net, app, concessioned)).invokeAction();
|
|||
</PRE><P>
|
|||
This example starts a <EM>SelectObject</EM> request. It returns a
|
|||
transition of the list of <CODE>concessioned</CODE> transitions
|
|||
passed as argument to the constructor. The ApplicationControl now
|
|||
searches for an application that handles this request. The request
|
|||
executer application is supposed to be an editor which asks the user
|
|||
to select a transition. Then the editor returns a transition chosen
|
|||
by the user. For a better understanding we discuss the implementation
|
|||
of the EmphasizeObjectsAction which request to emphasize some
|
|||
netobjects like Arcs, Places or Transitions.
|
|||
</P>
|
|||
<PRE>
|
|||
package de.huberlin.informatik.pnk.app.base;
|
|||
import java.util.Vector;
|
|||
import de.huberlin.informatik.pnk.kernel.*;
|
|||
import de.huberlin.informatik.pnk.appControl.*;
|
|||
/**
|
|||
* EmphasizeObjectsAction.java
|
|||
*
|
|||
* An application working on a net may emphasize
|
|||
* some netobjects (for example Places or Transitions)
|
|||
* using this ActionObject. The application specifies an
|
|||
* ApplicationControl. This tries to find another application as target
|
|||
* to perform the emphasize request. Therefore the ApplciationControl
|
|||
* checks if the targetapplication works on the same net and
|
|||
* implements the necessary interface.
|
|||
*
|
|||
* @author: gruenewa
|
|||
*/
|
|||
public class EmphasizeObjectsAction extends MetaActionObject {
|
|||
/*
|
|||
* A list of objects that should be emphasized by
|
|||
* an application for example an editor
|
|||
*/
|
|||
Vector emphasizeObjects = null;
|
|||
/**
|
|||
* Creates a new EmphasizeObjectsAction instance.
|
|||
*
|
|||
* @param ac an ApplicationControl the AC which should find a targetapplication
|
|||
* @param net a Graph the graph/net the targetapplication currently processes
|
|||
* @param initiator a MetaApplication initiator of this request
|
|||
* @param emphasizeObjects a Vector parameters for the request
|
|||
*/
|
|||
public EmphasizeObjectsAction(ApplicationControl ac,
|
|||
Graph net,
|
|||
MetaApplication initiator,
|
|||
Vector emphasizeObjects) {
|
|||
super(ac, net, initiator);
|
|||
this.emphasizeObjects = emphasizeObjects;
|
|||
}
|
|||
/**
|
|||
* method checkInterface
|
|||
*
|
|||
* The ApplicationControl uses this method to check all
|
|||
* available applications if they implement the necessary
|
|||
* interface to achieve this request.
|
|||
*
|
|||
* @param target an Object an application candidate
|
|||
* @return a boolean true if candidate is fine
|
|||
*/
|
|||
public boolean checkInterface(Object appCandidate) {
|
|||
return appCandidate instanceof ApplicationNetDialog;
|
|||
}
|
|||
/**
|
|||
* method performAction
|
|||
*
|
|||
* After the ApplicationControl has extracted a suitable application
|
|||
* it call's this method to execute the request.
|
|||
*
|
|||
* @param target a MetaApplication application for the request
|
|||
* @return an Object result of the request will always be null
|
|||
*/
|
|||
public Object performAction(MetaApplication target) {
|
|||
((ApplicationNetDialog) target).emphasizeObjects(emphasizeObjects);
|
|||
return null; // this request is one-way, no return value necessary
|
|||
}
|
|||
} // class EmphasizeObjectsAction
|
|||
</PRE><P>
|
|||
<A NAME="Application with Menu"></A>Take this example to design your
|
|||
own ActionObjects.
|
|||
</P>
|
|||
<H4>Application with Menu</H4>
|
|||
<P>Possibly you intend to write a more complex application with
|
|||
buttons and frames for example an editor. You want the application to
|
|||
set a menu in the ApplicationControl's menubar and to show this menu
|
|||
ever when an application's window got the focus. If your application
|
|||
implements an <CODE>getMenus()</CODE> method:
|
|||
</P>
|
|||
<PRE>
|
|||
public JMenu[] getMenus()
|
|||
</PRE><P>
|
|||
<A NAME="Load Applications"></A>the ApplicationControl uses this
|
|||
method to request an <CODE>java.lang.Array</CODE> of
|
|||
<CODE>javax.swing.JMenus</CODE>'s and sets these menus in it's
|
|||
menubar. If your application uses frames we recommend to use the
|
|||
<CODE>de.huberlin.informatik.pnk.app.base.MetaJFrame</CODE> class.
|
|||
This class implements some base functionality. It informs the
|
|||
ApplicationControl when the frame has got focus or it notifies the
|
|||
ApplicationControl when a window was closed. So the
|
|||
ApplicationControl knows which application currently works.
|
|||
</P>
|
|||
<H4>Load Applications</H4>
|
|||
<P>Presumed you have written a new application you have to announce
|
|||
it to the Petrinet Kernel's ApplicationControl. You do this by
|
|||
invoking the Petrinet Kernel's <EM>ToolSpecification</EM> mechanism.
|
|||
Edit the related <EM>toolSpecification.xml</EM> file by inserting an
|
|||
entry for your application. For the simulator application this entry
|
|||
would look something like this:
|
|||
</P>
|
|||
<PRE>
|
|||
< !-- Simulator Application -- >
|
|||
< !-- Embedding a simulator application using a reference to it's class file -- >
|
|||
< !-- Maximum 5 instances, you could also choose 'inf' for infinity -- >
|
|||
< application id="a5" mainClass="de.huberlin.informatik.pnk.app.Simulator" maxinstances="5" >
|
|||
< allowedNettypes >
|
|||
< !-- Here you have to enter references -- >
|
|||
< !-- of nettypes the simulator can work with -- >
|
|||
< ntref ref="n1"/ >
|
|||
< ntref ref="n6"/ >
|
|||
< /allowedNettypes >
|
|||
< /application >
|
|||
</PRE>
|
|||
<p>
|
|||
Use a TOOLspecificationfile to unite some nettypes and applications to one tool.
|
|||
For example the EchoSimulator tool has a specificationfile <em>toolSpecifications/EchoSimulator.xml</em>.
|
|||
You launch the EchoSimulator tool on commandline by initiating the ApplicationControl with
|
|||
the specificationfile as first argument.
|
|||
<p>
|
|||
<pre>
|
|||
java -classpath .:crimson.jar:jaxp.jar \
|
|||
de.huberlin.informatik.pnk.appControl.ApplicationControl \
|
|||
toolSpecifications/EchoSimulator.xml
|
|||
</pre>
|
|||
<p>
|
|||
The EchoSimulator tool consists of two nettypes, a <code>Echo</code> Net that represents
|
|||
the algorithm and a <code>graph</code>, used by the algorithm.
|
|||
It also inheres an editor application for animation,
|
|||
a simulator application that performs the algorithm and a MarkingsToInitial application to set the initial
|
|||
marking before you continue the simulation.
|
|||
All these components are enumerated in the specificationfile.
|
|||
<p>
|
|||
<pre>
|
|||
< ?xml version="1.0" encoding="UTF-8"? >
|
|||
< !DOCTYPE toolSpecification SYSTEM "toolSpecification.dtd" >
|
|||
< toolSpecification >
|
|||
< !-- Nettypes -- >
|
|||
< nettype id="n3" typeSpecification="file:netTypeSpecifications/Echo.xml"/ >
|
|||
< nettype id="n4" typeSpecification="file:netTypeSpecifications/graph.xml"/ >
|
|||
< !-- Applications -- >
|
|||
< application id="a1" mainClass="de.huberlin.informatik.pnk.editor.Editor" maxinstances="inf" >
|
|||
< /application >
|
|||
< application id="a3" mainClass="de.huberlin.informatik.pnk.app.MarkingsToInitial" maxinstances="inf" >
|
|||
< /application >
|
|||
< application id="a5" mainClass="de.huberlin.informatik.pnk.app.EchoSimulator" maxinstances="inf" >
|
|||
< allowedNettypes >
|
|||
< ntref ref="n4"/ >
|
|||
< /allowedNettypes >
|
|||
< /application >
|
|||
< !-- Input / Output Format Filters-- >
|
|||
< format id="pnml" ioClass="de.huberlin.informatik.pnk.appControl.PnmlInOut" >
|
|||
< /format >
|
|||
< !-- default settings -- >
|
|||
< standardNettype ref="n4"/ >
|
|||
< standardApplication ref="a1"/ >
|
|||
< standardFormat ref="pnml"/ >
|
|||
< /toolSpecification >
|
|||
</pre>
|
|||
<p>
|
|||
You can write a specificationfile per tool, or you put all your nettypes, applications and
|
|||
fileformatfilters into one specificationfile. So you will construct an universal monster tool.
|
|||
I favor the first variant.
|
|||
<p>
|
|||
<A NAME="Write Nettypes"></A>
|
|||
<H3>
|
|||
Write Nettypes</H3>
|
|||
<HR>
|
|||
There exists much petrinet theorie in the world and a lot of different petrinet formalism.
|
|||
You can find Place-Transition Net's, Algebraic Net's or Timed Net's and many others.
|
|||
The idea of the Petrinet Kernel is that you may create your own nettype using our concept of netextensions.
|
|||
Therefore you have to write a nettype specification.
|
|||
Then you have to notify the corresponding toolspecificationfile, that a new nettype exists and where
|
|||
it can be found. For instance a file <em>toolSpecifications/PTNetTool.xml</em> would contain something like this:
|
|||
<p>
|
|||
<PRE>
|
|||
< !DOCTYPE toolSpecification SYSTEM "toolSpecification.dtd" >
|
|||
< toolSpecification >
|
|||
< !-- Nettypes -- >
|
|||
< nettype id="n1" typeSpecification="file:netTypeSpecifications/PTNet.xml"/ >
|
|||
< !-- Applications -- >
|
|||
< !-- Here comes a list of applications ... -- >
|
|||
< !-- Input / Output -- >
|
|||
< !-- Here comes a list of Input / Output filters ... -- >
|
|||
< /toolSpecification >
|
|||
</PRE><p>
|
|||
Let's take a closer look at <em>netTypeSpecifications/PTNet.xml</em>.
|
|||
<PRE>
|
|||
< ?xml version="1.0" encoding="UTF-8"? >
|
|||
< !DOCTYPE netTypeSpecification SYSTEM "netTypeSpecification.dtd" >
|
|||
< netTypeSpecification name="PTNet" >
|
|||
< extendable class="de.huberlin.informatik.pnk.kernel.Net" >
|
|||
< extension name="firingRule" class="de.huberlin.informatik.pnk.netElementExtensions.llNet.SimpleRule"/ >
|
|||
< /extendable >
|
|||
< extendable class="de.huberlin.informatik.pnk.kernel.Place" >
|
|||
< extension name="marking" class="de.huberlin.informatik.pnk.netElementExtensions.llNet.NaturalNumber"/ >
|
|||
< extension name="initialMarking" class="de.huberlin.informatik.pnk.netElementExtensions.llNet.NaturalNumber"/ >
|
|||
< /extendable >
|
|||
< extendable class="de.huberlin.informatik.pnk.kernel.Transition" >
|
|||
< /extendable >
|
|||
< extendable class="de.huberlin.informatik.pnk.kernel.Arc" >
|
|||
< extension name="inscription" class="de.huberlin.informatik.pnk.netElementExtensions.llNet.NaturalNumber1"/ >
|
|||
< /extendable >
|
|||
< /netTypeSpecification >
|
|||
</PRE><p>
|
|||
The < netTypeSpecification name="PTNet" > tells us the name of the nettype. The same name will be shown
|
|||
in the ApplicationControl's <em>new Net</em> menu or stored in a pnml file.
|
|||
Then a list of <em>extendables</em> and it's <em>extensions</em>
|
|||
follows. The extendable implements the
|
|||
<code>de.huberlin.informatik.pnk.kernel.Extendable</code> interface. Extendables
|
|||
for example are:
|
|||
<p>
|
|||
<ul>
|
|||
<li> de.huberlin.informatik.pnk.kernel.Net
|
|||
<li> de.huberlin.informatik.pnk.kernel.Arc
|
|||
<li> de.huberlin.informatik.pnk.kernel.Place
|
|||
<li> de.huberlin.informatik.pnk.kernel.Transition
|
|||
<li> de.huberlin.informatik.pnk.kernel.Extension
|
|||
</ul>
|
|||
<p>
|
|||
The interface serves methods like:
|
|||
<p>
|
|||
<ul>
|
|||
<li> public Hashtable getExtIdToObject()
|
|||
// requests a java.util.Hashtable: String id -> Extensions ext
|
|||
<li> public boolean hasExtension(String id)
|
|||
// requests if extension with name: id, exists
|
|||
<li> public Extension getExtension(String id)
|
|||
// requests the extension object with name: id
|
|||
<li> public void setExtension(Object initiator, String id, String value)
|
|||
// request from application: initiator, in extensions with name: id, sets the extensionvalue to: value
|
|||
</ul>
|
|||
<p>
|
|||
For the extandable <code>de.huberlin.informatik.pnk.kernel.Place</code> an imaginable extension
|
|||
could be <em>marking</em>. The extensions implementation could be the class
|
|||
<code>de.huberlin.informatik.pnk.netElementExtensions.llNet.NaturalNumber</code>.
|
|||
So that's the code you have to put into the nettype-specificationfile:
|
|||
<p>
|
|||
<PRE>
|
|||
< extendable class="de.huberlin.informatik.pnk.kernel.Place" >
|
|||
< extension name="marking" class="de.huberlin.informatik.pnk.netElementExtensions.llNet.NaturalNumber"/ >
|
|||
</PRE>
|
|||
<p>
|
|||
As you can see an extension entry is formed by a name and a reference to a java class.
|
|||
In this case the extension's name is <em>marking</em>
|
|||
and the extensions's implementation is
|
|||
<code>de.huberlin.informatik.pnk.netElementExtensions.llNet.NaturalNumber</code>.
|
|||
When an extendable is generated (in this case a place) the extensions where build from
|
|||
the specification (an instance of de.huberlin.informatik.pnk.netElementExtensions.llNet.NaturalNumber
|
|||
will be initialized).
|
|||
<p>
|
|||
NOTE: The <em>name</em> of an extendable is a standard extension, so You have not to refer it in the nettype-specificationfile!
|
|||
<p>
|
|||
Now it's time to say something about the [ abstract classes | interfaces ]
|
|||
Marking, Inscription, Mode and FiringRule. These are very important to affect
|
|||
the behaviour of your nettype. To make your nettype work you have to implement these or you use one of
|
|||
our default implementations.
|
|||
<p>
|
|||
<h4><A NAME=Marking></A>Marking</h4>
|
|||
Let's start with the <em>Marking</em> extension.
|
|||
It is an abstact class. It serves methods like:
|
|||
<p>
|
|||
<pre>
|
|||
public abstract class Marking
|
|||
extends Extension implements Inscription {
|
|||
//************************************************************
|
|||
// These are the methods you have to implement to make the
|
|||
// Marking work.
|
|||
//************************************************************
|
|||
/**
|
|||
* Returns true if <code>marking</code> is contained in this marking.
|
|||
*/
|
|||
abstract public boolean contains(Marking marking);
|
|||
/**
|
|||
* Adds the markings. This method is called by
|
|||
* the <code>add(Marking marking)</code> method
|
|||
* of this marking.
|
|||
*/
|
|||
abstract protected void localAdd(Marking marking);
|
|||
/**
|
|||
* Subtracts the markings. This method is called by
|
|||
* the <code>add(Marking marking)</code> method
|
|||
* of this marking.
|
|||
*/
|
|||
abstract protected void localSub(Marking marking);
|
|||
//************************p************************************
|
|||
// These are the methods you may use.
|
|||
//************************************************************
|
|||
public Marking evaluate() { return this; }
|
|||
/**
|
|||
* Add operation of an Marking.
|
|||
* Uses the <code>localAdd(Marking marking)</code> method
|
|||
* and updates the new value of the marking in kernel.
|
|||
*/
|
|||
final public void add(Marking marking) { ... }
|
|||
/**
|
|||
* Subtract operation of an Marking.
|
|||
* Uses the <code>localSub(Marking marking)</code> method
|
|||
* and updates the new value of the marking in kernel.
|
|||
*/
|
|||
final public void sub(Marking marking) { ... }
|
|||
/**
|
|||
* Returns true if this marking is empty.
|
|||
*/
|
|||
final public boolean isEmpty( ){ ... }
|
|||
} // public interface Marking
|
|||
</pre>
|
|||
<p>
|
|||
As you can see it is expected that you implement the methods:
|
|||
<p>
|
|||
<ul>
|
|||
<li> public boolean contains(Marking marking);
|
|||
<li> protected void localAdd(Marking marking);
|
|||
<li> protected void localSub(Marking marking);
|
|||
</ul>
|
|||
<p>
|
|||
<h4><A NAME="Inscription"></A>Inscription</h4>
|
|||
<p>
|
|||
The <em>inscription</em> extension of an arc is an interface.
|
|||
<p>
|
|||
<pre>
|
|||
/**
|
|||
* The template for the implementation of an <em> inscription </em> of an
|
|||
* {@link Arc arc}.
|
|||
* The <code> "inscription" </code> of an
|
|||
* arc is a standard {@link Extension extension}. Whenever you design
|
|||
* your own {@link Net Petri Net} type you either need to implement a
|
|||
* custom inscription class (derived from class Extension and
|
|||
* implementing <code>Inscription</code>) or you use one of the
|
|||
* standard implementations (e.g. {@link Arc arc} multiplicities for
|
|||
* Place/Transition-Nets).
|
|||
*/
|
|||
public interface Inscription
|
|||
{
|
|||
Marking evaluate();
|
|||
}
|
|||
</pre>
|
|||
<p>
|
|||
It declares an <code>evaluate()</code> method that returns an object
|
|||
of a <code>Marking</code> class. For example you want to
|
|||
subtract tokens from a place using the inscription of an arc. You could program
|
|||
something like
|
|||
<p>
|
|||
<pre>
|
|||
// get sourcenode of arc
|
|||
Place sourceNode = (Place) arc.getSource();
|
|||
// get marking of sourcenode
|
|||
Marking marking = sourceNode.getMarking();
|
|||
// get inscription of arc
|
|||
Inscription inscription = arc.getInscription();
|
|||
// subtract the value of arc's inscription from sourcenode's marking
|
|||
marking.sub(inscription.evaluate());
|
|||
</pre>
|
|||
<p>
|
|||
I hope this clears the idea of the <code>Inscription</code> interface
|
|||
and the <code>Marking</code> class. You need both to implement the
|
|||
<em>firingRule</em> extension of a net.
|
|||
<p>
|
|||
<h4><A NAME="FiringRule"></A>FiringRule</h4>
|
|||
<p>
|
|||
A <code>de.huberlin.informatik.pnk.kernel.Net</code> is recommended to have a <em>firingRule</em>.
|
|||
This extension should implement the <code>de.huberlin.informatik.pnk.netElementExtensions.base.FiringRule</code>
|
|||
interface. This interface demands as previously mentioned the methods:
|
|||
<p>
|
|||
<pre>
|
|||
/**
|
|||
* Is the template for implementing the <em> firing rule </em> of a
|
|||
* {@link de.huberlin.informatik.pnk.kernel.Net Petri Net}.
|
|||
*
|
|||
* The firing rule of a net is a
|
|||
* standard {@link de.huberlin.informatik.pnk.kernel.Extension extension}.
|
|||
* Whenever you design your own
|
|||
* Petri Net type you either need to implement a custom
|
|||
* firing rule class (derived from class
|
|||
* {@link de.huberlin.informatik.pnk.kernel.Extension Extension} and implementing
|
|||
* <code> FiringRule </code>) or you use one of the standard
|
|||
* implementations (e.g. the 'Hamburg' rule for Place/Transition-Nets).
|
|||
*/
|
|||
public interface FiringRule
|
|||
{
|
|||
/**
|
|||
* Parses all Extensions with an internal value depending on
|
|||
* (possibly edited) other extensions.
|
|||
*/
|
|||
void checkContextAndParseExtensions();
|
|||
/**
|
|||
* Fires the set of {@link Transition transitions} given by
|
|||
* <code>transitions</code>.
|
|||
* The transitions are fired simultaneously. Usually
|
|||
* an order is practically introduced due to the sequential nature of
|
|||
* the implementation of <code>fire</code>, but no assumptions should me
|
|||
* made about this order.
|
|||
*/
|
|||
void fire(Vector transitions);
|
|||
/**
|
|||
* Returns the set of all {@link #isConcessioned concessioned} {@link
|
|||
* Transition transitions}.
|
|||
*/
|
|||
Vector getAllConcessioned();
|
|||
/**
|
|||
* Returns the set of all {@link #isConcessioned concessioned}
|
|||
* {@link Transition transitions}, which are in the
|
|||
* set <code>inclTrans</code> and not in <code>exclTrans</code>.
|
|||
* The returned set contains each {@link #isConcessioned
|
|||
* concessioned} transition meeting the additional
|
|||
* criteria.
|
|||
* Both sets may possibly be empty. Set <code>inclTrans</code> is empty
|
|||
* or set <code>exclTrans</code> equals the set of all transitions
|
|||
* implies that an empty set will be returned. If <code>exclTrans</code>
|
|||
* is empty, no transition is a priori excluded from
|
|||
* the eventually returned set.
|
|||
*/
|
|||
Vector getAllConcessioned(Vector inclTrans, Vector exclTrans);
|
|||
/**
|
|||
* Returns the set of all simultaneously fireable sets ({@link #isStep
|
|||
* steps}) of {@link Transition transitions}.
|
|||
* @see #getStep()
|
|||
*/
|
|||
Vector getAllSteps();
|
|||
/**
|
|||
* Returns the set of all sets ({@link #isStep steps}) of
|
|||
* simultaneously fireable {@link Transition transitions}.
|
|||
* Each returned {@link #isStep step} has at least one
|
|||
* transition in common with <code>inclTrans</code> and the
|
|||
* intersection with <code>exclTrans</code> is empty.
|
|||
*/
|
|||
Vector getAllSteps(Vector inclTrans, Vector exclTrans);
|
|||
/**
|
|||
* Returns a reference to a {@link #isConcessioned concessioned}
|
|||
* transition.
|
|||
*/
|
|||
Transition getConcessioned();
|
|||
/**
|
|||
* Returns a reference to a {@link #isConcessioned concessioned}
|
|||
* transition, which is in the transition
|
|||
* set <code>inclTrans</code> and not in <code>exclTrans</code>.
|
|||
* Both sets may possibly be empty. An empty set <code>inclTrans</code>
|
|||
* or a set <code>exclTrans</code> equal to the set of all
|
|||
* transitions always causes an exception. If
|
|||
* <code>exclTrans</code> is empty, no transition is
|
|||
* a priori excluded from the set of possible return values.
|
|||
*/
|
|||
Transition getConcessioned(Vector inclTrans, Vector exclTrans);
|
|||
/**
|
|||
* Returns a simultaneously fireable set ({@link #isStep step}) of
|
|||
* {@link Transition transitions}.
|
|||
* The step is simultaneously fireable according to
|
|||
* the implemented firing rule. Naturally all
|
|||
* transitions in a step are {@link #isConcessioned
|
|||
* concessioned}.
|
|||
* The returned {@link #isStep step} may serve as input for {@link
|
|||
* #fire fire(step)}.
|
|||
*/
|
|||
Vector getStep();
|
|||
/**
|
|||
* Returns a simultaneously fireable subset ({@link #isStep step}) of
|
|||
* set <code> transitions</code>.
|
|||
* The {@link #isStep step} has at least one
|
|||
* transition in common with <code>inclTrans</code> and the
|
|||
* intersection with <code>exclTrans</code> is empty.
|
|||
* The step is fireable according to the implemented
|
|||
* firing rule. Naturally all transitions in the
|
|||
* step are {@link #isConcessioned concessioned}.
|
|||
*/
|
|||
Vector getStep(Vector transitions);
|
|||
/**
|
|||
* Returns whether the given <code>transition</code> is
|
|||
* concessioned.
|
|||
* The definition of concessioned varies even among the same class of
|
|||
* {@link de.huberlin.informatik.pnk.kernel.Net Petri Nets}. The most commonly used definition for
|
|||
* P/T-Nets simply demands that each {@link de.huberlin.informatik.pnk.kernel.Place place} in the preset
|
|||
* of a {@link Transition transition} must carry at least as many tokens
|
|||
* as the multiplicity of the {@link de.huberlin.informatik.pnk.kernel.Arc arc} from the
|
|||
* place to the transition.
|
|||
*/
|
|||
boolean isConcessioned( Transition transition);
|
|||
/**
|
|||
* Returns whether a set of {@link Transition transitions} is
|
|||
* simultaneously fireable.
|
|||
* Be aware of the difference between <em>simultaneously fireable</em>
|
|||
* and <em>fireable in an arbitrary order</em> under certain
|
|||
* circumstances.
|
|||
* The maximal step firing rule for P/T-Nets is an example for the
|
|||
* importance of that difference. In that case a step is defined as an
|
|||
* inclusion-maximal set of simultaneously fireable {@link Transition
|
|||
* transitions}. Under the normal firing rule for P/T-Nets the {@link
|
|||
* Transition transitions} in this set could be {@link #fire fired} in
|
|||
* an arbitrary order. One can imagine a situation where a
|
|||
* transition t, which is not member of the step, can only
|
|||
* be {@link #isConcessioned concessioned} <em>during</em> the {@link
|
|||
* #fire firing} of the transitions in the step in
|
|||
* an appropriate order. The freedom of choosing the order is taken away
|
|||
* by the maximal step firing rule, since there is no 'during'. It all
|
|||
* happens in the very same moment. Consequently
|
|||
* transition t can never become {@link #isConcessioned concessioned}.
|
|||
*
|
|||
* What is even more astonishing: because of that feature of P/T-Nets
|
|||
* with the maximal step firing rule it is possible to simulate the
|
|||
* <em>decrement if not zero and goto i, otherwise goto j</em> operation
|
|||
* of a counter automata, which is as expressive as and as hard to
|
|||
* analyze as a Turing machine.
|
|||
*/
|
|||
boolean isStep( Vector transitions);
|
|||
} // public interface FiringRule
|
|||
</pre>
|
|||
<p>
|
|||
As showed in the simulator example, you use the firingrule extension to request
|
|||
concessioned transitions and fire them. For an sample implementation you might see the
|
|||
<code>de.huberlin.informatik.pnk.netElementExtensions.llNet.SimpleRule</code>. You can use
|
|||
this implementation as default. It profits by methods of the
|
|||
<code>de.huberlin.informatik.pnk.netElementExtensions.base.Marking</code> class and the
|
|||
<code>de.huberlin.informatik.pnk.netElementExtensions.base.Inscription</code> interface.
|
|||
An possible implementation of the <code>fire()</code> methode in a FiringRule object could be:
|
|||
<p>
|
|||
<pre>
|
|||
/**
|
|||
* A sample implementation of methode fire() in FiringRule.
|
|||
* Fires the given <code>transition</code> by subtracting
|
|||
* markings from all places in preset of transition and
|
|||
* adding markings to all places in postset of transition.
|
|||
*/
|
|||
public void fire(Transition transition) {
|
|||
Vector edges;
|
|||
/*
|
|||
* subtract markings from places in preset of transition
|
|||
*/
|
|||
edges = transition.getIncomingEdges();
|
|||
for(int i = 0; i < edges.size(); i++) {
|
|||
Edge edge = (Edge) edges.get(i);
|
|||
Inscription inscription = (Inscription) edge.getExtension("inscription");
|
|||
Marking marking = ((Place) edge.getSource()).getMarking();
|
|||
marking.sub(inscription.evaluate());
|
|||
} // end for
|
|||
/*
|
|||
* add markings to places in postset of transition
|
|||
*/
|
|||
edges = transition.getOutgoingEdges();
|
|||
for(int i = 0; i < edges.size(); i++) {
|
|||
Edge edge = (Edge) edges.get(i);
|
|||
Inscription inscription = (Inscription) edge.getExtension("inscription");
|
|||
Marking marking = ((Place) edge.getTarget()).getMarking();
|
|||
marking.add(inscription.evaluate());
|
|||
} // end for
|
|||
} // public void fire
|
|||
</pre>
|
|||
<p>
|
|||
A second example shows a practicable implementation of the <code>isConcessioned()</code>
|
|||
method in a FiringRule object:
|
|||
<p>
|
|||
<pre>
|
|||
/**
|
|||
* Returns whether the given
|
|||
* <code>transition</code> is concessioned. <BR>
|
|||
*/
|
|||
public boolean isConcessioned(Transition transition) {
|
|||
boolean to_return = true; // indicates that transition is concessioned
|
|||
// enumerate on all incoming edges,
|
|||
// check if there is one place as edge sourcenode
|
|||
// that doesn't activate the transition
|
|||
Vector edges = transition.getIncomingEdges();
|
|||
for(int i = 0; i < edges.size(); i++) {
|
|||
Edge edge = (Edge) edges.get(i);
|
|||
Inscription inscription = (Inscription) edge.getExtension("inscription");
|
|||
Marking marking = ((Place)edge.getSource()).getMarking();
|
|||
if( ! marking.contains(inscription.evaluate()))
|
|||
to_return = false; // now it's clear, the transition is not activated
|
|||
} // end for
|
|||
return to_return;
|
|||
} // boolean isConcessioned
|
|||
</pre>
|
|||
<p>
|
|||
<p>
|
|||
<HR>
|
|||
<ADDRESS><A HREF="mailto:gruenewa@informatik.hu-berlin.de">Alexander Gruenewald</A></ADDRESS>
|
|||
<P><!-- Created: Wed May 16 20:19:15 CEST 2001 --><!-- hhmts start -->Last
|
|||
modified: Tue Aug 7 15:34:01 MET DST 2001<!-- hhmts end -->
|
|||
</P>
|
|||
</BODY>
|
|||
</HTML>
|