Projet

Général

Profil

Télécharger (46 ko) Statistiques
| Branche: | Tag: | Révision:
package de.huberlin.informatik.pnk.appControl;

import de.huberlin.informatik.pnk.exceptions.NetParseException;
import de.huberlin.informatik.pnk.kernel.*;
import java.awt.Point;
import java.io.*;
import java.net.URL;
import java.util.*;

/**
NetInOut implements a parser to load a .net-file used by the old
python-pnk. It inherits InOut to be compatible with pnk file formats.
The load method starts the parser. The save method saves a net
using the python-pnk file format.
*/
public class NetInOut extends InOut {
final String pytToJavaTable = "netTypeSpecifications/netTypesPytJava.table";
/*Token constants used for nextToken calls*/
final int NUMBER = 256,
WORD = 257,
LF = 258,
NET = 259,
NET_END = 260,
SPECIFICATION = 261,
PLACES = 262,
TRANSITIONS = 263,
ARCS = 264,
MARKING = 265,
ARROW = 266,
STRING = 267,
NE_STRING = 268,
EDITOR_INFOS = 269,
END_EDITOR = 270,
PAGES = 271,
PLACE = 272,
TRANSITION = 273,
ARC = 274,
QUOTED_STRING = 275,
EOF = 65535;

final double GRAPH_FACTOR = 1.5;
private int line = 1; // count parsed lines
private Vector restoredChars; // token that does not match are restored here
private InputStream file = null; // net to load
private Graph theNet = null;
private Hashtable extensionTable; // translation table for extensions (Python <-> Java)
/**
inOutName is set to "PNK-NET". This variable is inherited from InOut.
It is used as a file format discription. The text is displayed in the
file/save and file/open dialog.
*/
public static String inOutName = "PNK-Net";
/**
stdFileExt is set to "net". The standard file extension of this file
format is ".net".
*/
public static String stdFileExt = "net";
/**
multipleAllowed is set to true. Saving and Loading multiple nets is allowed.
*/
public static Boolean multipleAllowed = new Boolean(true);

int idCounter = 1; // the saved net gets new numerical ID's
Hashtable knownIds = null; // already translated ID's (ID -> numerical ID)

OutputStream fileOut = null;

/**
Constructor creates a new NetInOut object. The application control
object must be known. It is specified by the first parameter of
the constructor.
*/
public NetInOut(ApplicationControl ac) {
super(ac);
restoredChars = new Vector(10, 1);
extensionTable = new Hashtable();
}

private void dumpHash() {
Hashtable theHash;
for (Enumeration hashKeys = extensionTable.keys(), hashVals = extensionTable.elements();
hashKeys.hasMoreElements() && hashVals.hasMoreElements(); ) {
System.err.println(hashKeys.nextElement() + ":");
theHash = (Hashtable)hashVals.nextElement();
for (Enumeration oldExtensions = theHash.keys(), newExtensions = theHash.elements();
oldExtensions.hasMoreElements() && newExtensions.hasMoreElements(); ) {
System.err.println(" " + oldExtensions.nextElement() + " = " + newExtensions.nextElement());
}
System.err.println(";");
}
}

/*****************************************************************
************************ Start of Parser ************************
*****************************************************************/

/*Throws NetParseException; method is used by nextToken-method*/
private void error(String message) throws NetParseException {
NetParseException theException = new NetParseException("Parse-Error occured on line " + line + ": " + message);

throw theException;
}

/*get the next character either from restoredChars buffer or
(if buffer is empty) from input stream*/
private int getChar() {
int retval = 0;

if (restoredChars.size() > 0) {
retval = ((Integer)restoredChars.firstElement()).intValue();
restoredChars.removeElementAt(0);
} else {
try {
retval = file.read();
} catch (Throwable e) {
retval = EOF;
}
if (retval == -1)
retval = EOF;
}

return retval;
}

/*translate the ID of a netObject into a numerical ID
(alpha-numerical ID's are not allowed in this file format)*/
private String getNewId(Extendable netObject) {
String oldId = netObject.getId(); // get ID
String newId;

if (knownIds == null)
knownIds = new Hashtable();
newId = (String)knownIds.get(oldId); // already translated?
if (newId == null) {
newId = Integer.toString(idCounter); // get new ID from idCounter
knownIds.put(oldId, newId);
idCounter++;
}
return newId;
}

private String getPnmlNodeID(String pytID) {
String testID;
Node testNode;

/*Belongs the ID to a place?*/
testID = "p" + pytID;
testNode = theNet.getNodeById(testID);
if (testNode != null)
return testID;

/*Belongs the ID to a transition?*/
testID = "t" + pytID;
testNode = theNet.getNodeById(testID);
if (testNode != null)
return testID;

/*matching node ID could not be found*/
return null;
}

/*inserts an extension-translation into a specific hashtable (one hashtable for each
block type: PLACE, TRANSITION, ARC and NET) in extensionTable*/
private void insertExtTab(String block, String oldExt, String newExt) {
Hashtable blockHash;

blockHash = (Hashtable)extensionTable.get(block);
if (blockHash == null)
blockHash = new Hashtable();
blockHash.put(oldExt, newExt);
extensionTable.put(block, blockHash);
}

/*translates a given extension using the extension translation table*/
private String javaExt2Pyt(String ext, String type) {
Hashtable hashtab = (Hashtable)extensionTable.get(type);
String pytNameOfExt = null;
if (hashtab != null)
pytNameOfExt = (String)hashtab.get(ext); // translate Extension
if (pytNameOfExt == null || hashtab == null)
pytNameOfExt = ext;
return pytNameOfExt;
}

/**
Loads a new net whose location is specified by 'theURL' and starts the
parsing process. The file format of the net corresponds to the file format
used by the pnk python implementation. This method returns a vector, that
contains the new net at the first position.
*/
public Vector load(URL theURL) {
Vector v = new Vector();

try {
file = new FileInputStream(theURL.getFile());
} catch (FileNotFoundException e) {
System.err.println("Net-File not found!!!");
return null;
}

try {
parse_net(); // start parsing
v.addElement(theNet);
} catch (NetParseException e) { // an error occured while parsing process
System.err.println(e.getMessage());
}

return v;
}

/*'String LF {LF}' can be used instead of a simple LF*/
private void newline() throws NetParseException {
nextToken(STRING, true);
nextToken(LF, true);
while (nextToken(LF, false) != null) {; }
}

/**
Context sensitive lexer: tries to match the next token with the token-type
specified by 'token' (-> see token constants above) and returns the string,
if it matches. If the next token does not match the token-type, a
NetParserException will be thrown, if 'do_error' is true. Else 'null' will
be returned (without throwing an exception).
*/
private String nextToken(int token, boolean do_error) throws NetParseException {
final int ST_NUMBER0 = 0,
ST_NUMBER1 = 1,
ST_NUMBER2 = 2,
ST_NUMBER3 = 3,
ST_QUOTSTRING0 = 0,
ST_QUOTSTRING1 = 1;
StringBuffer strbuf = new StringBuffer();
String tokenValue, expectedToken = null;
int lastbyte = 0, state = 0;

lastbyte = getChar(); // read first char
/*eat up white spaces*/
while (lastbyte == ' ' || lastbyte == '\t' || lastbyte == '\r') {
lastbyte = getChar();
}

/*return next sign, if requested*/
if (token <= 255) {
if (token == lastbyte)
return new Character((char)token).toString();
else {
if (do_error)
error("'" + new Character((char)token).toString() + "' expected!!!");
else {
restoreToken(lastbyte);
return null;
}
}
}
/*get expectedToken-String for keywords*/
switch (token) {
case NET: expectedToken = "NET"; break;
case NET_END: expectedToken = "NET_END"; break;
case SPECIFICATION: expectedToken = "SPECIFICATION"; break;
case PLACES: expectedToken = "PLACES"; break;
case TRANSITIONS: expectedToken = "TRANSITIONS"; break;
case ARCS: expectedToken = "ARCS"; break;
case MARKING: expectedToken = "MARKING"; break;
case ARROW: expectedToken = "-->"; break;
case EDITOR_INFOS: expectedToken = "EDITOR_INFOS"; break;
case END_EDITOR: expectedToken = "END_EDITOR"; break;
case PAGES: expectedToken = "PAGES"; break;
case PLACE: expectedToken = "PLACE"; break;
case TRANSITION: expectedToken = "TRANSITION"; break;
case ARC: expectedToken = "ARC"; break;
}

while (true) {
tokenValue = strbuf.toString();
strbuf.append((char)lastbyte);
switch (token) {
case WORD: /*read a word*/
if (lastbyte == ' ' || lastbyte == '\t' || lastbyte == '\n' || lastbyte == EOF) {
if (tokenValue.length() == 0) {
if (do_error)
error("Word expected!!!");
else {
restoreToken(strbuf.toString());
return null;
}
} else {
restoreToken(lastbyte);
return tokenValue;
}
}
break;
case NE_STRING: /*read a non-empty string*/
if (lastbyte == '\n' || lastbyte == EOF) {
if (do_error)
error("String expected!!!");
else {
restoreToken(strbuf.toString());
return null;
}
} else
token = STRING;
break;
case STRING: /*read a string*/
if (lastbyte == '\n' || lastbyte == EOF) {
restoreToken(lastbyte);
return tokenValue;
}
break;
case QUOTED_STRING: /*read a quoted 'string'*/
switch (state) {
case ST_QUOTSTRING0:
if (lastbyte != '\'') {
if (do_error)
error("Quoted String expected!!!");
else {
restoreToken(strbuf.toString());
return null;
}
} else
state = ST_QUOTSTRING1;
break;
case ST_QUOTSTRING1:
if (lastbyte == EOF) {
if (do_error)
error("closing ' expected!!!");
else {
restoreToken(strbuf.toString());
return null;
}
} else if (lastbyte == '\'') {
return tokenValue.substring(1);
}
break;
}
break;
case NUMBER: /*read a number*/
switch (state) {
case ST_NUMBER0:
if (Character.isDigit((char)lastbyte))
state = ST_NUMBER1;
else if (lastbyte == '-')
state = ST_NUMBER0;
else {
if (do_error)
error("Number expected!!!");
else {
restoreToken(strbuf.toString());
return null;
}
}
break;
case ST_NUMBER1:
if (lastbyte == '.')
state = ST_NUMBER2;
else if (!Character.isDigit((char)lastbyte)) {
restoreToken(lastbyte);
return tokenValue;
}
break;
case ST_NUMBER2:
if (Character.isDigit((char)lastbyte))
state = ST_NUMBER3;
else {
if (do_error)
error("Number expected!!!");
else {
restoreToken(strbuf.toString());
return null;
}
}
break;
case ST_NUMBER3:
if (!Character.isDigit((char)lastbyte)) {
restoreToken(lastbyte);
return tokenValue;
}
break;
}
break;
case NET: /*read a specific keyword*/
case NET_END:
case SPECIFICATION:
case PLACES:
case TRANSITIONS:
case ARCS:
case MARKING:
case ARROW:
case EDITOR_INFOS:
case END_EDITOR:
case PAGES:
case PLACE:
case TRANSITION:
case ARC:
if (tokenValue.compareTo(expectedToken) == 0) {
restoreToken(lastbyte);
return tokenValue;
} else if (tokenValue.length() >= expectedToken.length() || lastbyte == EOF) {
if (do_error)
error(expectedToken + " expected!!!");
else {
restoreToken(strbuf.toString());
return null;
}
}
break;
case LF: /*read a line feed*/
if (tokenValue.compareTo("\n") == 0) {
line++;
restoreToken(lastbyte);
return tokenValue;
} else if (tokenValue.length() >= 1 || lastbyte == EOF) {
if (do_error)
error("LineFeed expected!!!");
else {
restoreToken(strbuf.toString());
return null;
}
}
break;
}
lastbyte = getChar(); // next character
}
//return null;
}

/*write a line feed*/
private void nl() throws IOException {
fileOut.write(10);
}

/**
parse an arc-block
*/
private void parse_arcs() throws NetParseException {
String source, target, ID, ArcInscription;
Member Arc;

newline();

while (nextToken('|', false) != null) {
source = getPnmlNodeID(nextToken(NUMBER, true)); //Source-Node
if (source == null)
error("Source-Node of Arc not defined before!");
nextToken(ARROW, true);
target = getPnmlNodeID(nextToken(NUMBER, true)); //Target-Node
if (target == null)
error("Target-Node of Arc not defined before!");
ID = "a" + nextToken(NUMBER, true); //ID of Arc
Arc = new Arc((Net)theNet, source, target, this, ID); // register new Arc!!
newline();

/*Read-arcInscription (String-Collection)*/
ArcInscription = parse_StringCollection();
nextToken(';', true);
setExtension(Arc, "inscription", ArcInscription); //set Arc-Inscription!!!

newline();
parse_Extension(Arc, "ARC");
newline();
}
nextToken(';', true);
newline();
}

/**
place-, transition-, arc-, and marking-blocks can be mixed
*/
private void parse_blocks() throws NetParseException {
nextToken('|', true);
if (nextToken(NET_END, false) != null)
return;

if (nextToken(PLACES, false) != null)
parse_places();
else if (nextToken(TRANSITIONS, false) != null)
parse_transitions();
else if (nextToken(ARCS, false) != null)
parse_arcs();
else if (nextToken(MARKING, false) != null)
parse_marking();
else
parse_globalExtension();

parse_blocks();
}

/**
graphical information of arcs
*/
private void parse_edArcs() throws NetParseException {
String Page;
int pageNum;
Arc anArc;

newline();

while (nextToken(';', false) == null) {
anArc = (Arc)theNet.getEdgeById("a" + nextToken(NUMBER, true)); //the Arc-Object
if (anArc == null)
error("Arc was not defined before!");
nextToken(':', true);
newline();
Page = nextToken(NUMBER, true); //ID of Page
pageNum = (int)Double.parseDouble(Page);
nextToken(NUMBER, true); //first Node-Object????
nextToken(NUMBER, true); //second Node-Object???

anArc.setPosition(new Point(), pageNum); // ???

/*************************************/
/*Drag-Point-Liste fehlt hier noch!!!*/
/*IDofNode-Reference wofür?????? */
/*************************************/
newline();
parse_objectExtension(anArc, Page, "ARC");
nextToken('.', true);
newline();
}

newline();
}

/**
blocks of the editor information part can be mixed
*/
private void parse_edBlocks() throws NetParseException {
if (nextToken(PAGES, false) != null)
parse_edPages();
else if (nextToken(PLACE, false) != null)
parse_edPlaces();
else if (nextToken(TRANSITION, false) != null)
parse_edTransitions();
else if (nextToken(ARC, false) != null)
parse_edArcs();
else
return;

parse_edBlocks();
}

/**
start parsing editor information
*/
private void parse_edNet() throws NetParseException {
if (nextToken(EDITOR_INFOS, false) != null) {
newline();
parse_edBlocks();
nextToken(END_EDITOR, true);
newline();
}
}

/**
parse page information
*/
private void parse_edPages() throws NetParseException {
String ID, width, height, xPos, yPos, visible;

newline();

while (nextToken(';', false) == null) {
ID = nextToken(NUMBER, true); //ID of Page
width = nextToken(NUMBER, true); //width
nextToken('x', true);
height = nextToken(NUMBER, true); //height
nextToken('+', true);
xPos = nextToken(NUMBER, true); //aboveLeftX
nextToken('+', true);
yPos = nextToken(NUMBER, true); //aboveLeftY

/************************************************/
/*View-State in PNK2 noch nicht implementiert!!!*/
/************************************************/
visible = nextToken('0', false);
if (visible == null) //viewstate
visible = nextToken('1', true);

/*******************************/
/*Pages noch nicht eingefügt!!!*/
/*******************************/

newline();
}

newline();
}

/**
graphical information of places
*/
private void parse_edPlaces() throws NetParseException {
String ID, Page, absX, absY;
Place aPlace;

newline();

while (nextToken(';', false) == null) {
ID = "p" + nextToken(NUMBER, true); //ID of Place
aPlace = (Place)theNet.getNodeById(ID);
if (aPlace == null)
error("Place was not defined before!");
nextToken(':', true);
newline();
Page = nextToken(NUMBER, true); //ID of Page
absX = nextToken(NUMBER, true); //absolute X
absY = nextToken(NUMBER, true); //absolute Y
aPlace.setPosition(new Point((int)(Double.parseDouble(absX) * GRAPH_FACTOR),
(int)(Double.parseDouble(absY) * GRAPH_FACTOR)),
(int)Double.parseDouble(Page));
newline();
parse_objectExtension(aPlace, Page, "PLACE");
nextToken('.', true);
newline();
}

newline();
}

/**
graphical information of transitions
*/
private void parse_edTransitions() throws NetParseException {
String ID, Page, absX, absY;
Transition aTransition;

newline();

while (nextToken(';', false) == null) {
ID = "t" + nextToken(NUMBER, true); //ID of Transition
aTransition = (Transition)theNet.getNodeById(ID);
if (aTransition == null)
error("Transition was not defined before!");
nextToken(':', true);
newline();
Page = nextToken(NUMBER, true); //ID of Page
absX = nextToken(NUMBER, true); //absolute X
absY = nextToken(NUMBER, true); //absolute Y
aTransition.setPosition(new Point((int)(Double.parseDouble(absX) * GRAPH_FACTOR),
(int)(Double.parseDouble(absY) * GRAPH_FACTOR)),
(int)Double.parseDouble(Page));
newline();
parse_objectExtension(aTransition, Page, "TRANSITION");
nextToken('.', true);
newline();
}

newline();
}

/**
parses extension section of arc-, place- and transition-blocks
*/
private void parse_Extension(Extendable netObject, String type) throws NetParseException {
String name, nameOfExt = null, valueOfExt;
Hashtable hashtab = (Hashtable)extensionTable.get(type);

while (nextToken(';', false) == null) {
nextToken('|', true);
name = nextToken(NE_STRING, true);
if (hashtab != null)
nameOfExt = (String)hashtab.get(name); // translate Extension
if (nameOfExt == null || hashtab == null)
nameOfExt = name;
newline();
valueOfExt = parse_StringCollection();
nextToken(';', true);
newline();
setExtension(netObject, nameOfExt, valueOfExt);
}
}

/**
parses global extensions
*/
private void parse_globalExtension() throws NetParseException {
String name, nameOfExt = null, valueOfExt;
Hashtable hashtab = (Hashtable)extensionTable.get("NET");

name = nextToken(NE_STRING, false);
if (hashtab != null)
nameOfExt = (String)hashtab.get(name); // translate Extension
if (nameOfExt == null || hashtab == null)
nameOfExt = name;
newline();
valueOfExt = parse_StringCollection();
nextToken(';', true);
newline();
setExtension(theNet, nameOfExt, valueOfExt);
}

/**
parse a marking-block
*/
private void parse_marking() throws NetParseException {
Place place;
String marking;

newline();

while (nextToken('|', false) != null) {
place = (Place)theNet.getNodeById("p" + nextToken(NUMBER, true)); //ID of Place
if (place == null) // Place must be defined before
error("Place was not defined before!");
newline();

/*initialMarking = StringCollection*/
marking = parse_StringCollection();
nextToken(';', true);
setExtension(place, "initialMarking", marking); //Marking of Place
setExtension(place, "marking", marking);

newline();
}
nextToken(';', true);
newline();
}

/**
The parsing process starts with this method. It calls the
methods parse_netSpecification, parse_blocks and parse_edNet
*/
private void parse_net() throws NetParseException {
String net_name;

nextToken('|', true);
nextToken(NET, true);
newline();
nextToken('|', true);
net_name = nextToken(STRING, true); //name of net
newline();

parse_netSpecification();
theNet.setName(net_name);
theNet.setId(net_name);

parse_blocks();

newline();
parse_edNet();
}

/**
parses net specification and constructs new net
*/
private void parse_netSpecification() throws NetParseException {
String net_spec;

nextToken('|', true);
nextToken(SPECIFICATION, true);
net_spec = nextToken(WORD, true); //name of Specification
net_spec = setExtensionTablePytJava(net_spec);

theNet = ac.getNewNet(net_spec); // get new net!!!
if (theNet == null)
error("Net type unknown!");
newline();
}

/**
graphical information of object extensions (e.g. initial marking position)
*/
private void parse_objectExtension(Member member, String page, String type) throws NetParseException {
Extension extension;
String name, nameOfExt = null, relativX, relativY;
Hashtable hashtab = (Hashtable)extensionTable.get(type);
if (nextToken('{', false) != null) {
while (nextToken('}', false) == null) {
name = nextToken(QUOTED_STRING, true);

/*old extension ===>>> new Extension!!!*/
if (hashtab != null)
nameOfExt = (String)hashtab.get(name); // translate Extension
if (nameOfExt == null || hashtab == null)
nameOfExt = name;
extension = member.getExtension(nameOfExt); //Get Extension

nextToken(':', true);
nextToken('(', true);
relativX = nextToken(NUMBER, true); //relativX
nextToken(',', true);
relativY = nextToken(NUMBER, true); //relativY
/*set relative position of object extension*/
if (extension != null)
extension.setOffset(new Point((int)(Double.parseDouble(relativX) * GRAPH_FACTOR),
(int)(Double.parseDouble(relativY) * GRAPH_FACTOR)),
(int)Double.parseDouble(page));
nextToken(',', true);

/************************************************/
/*View-State in PNK2 noch nicht implementiert!!!*/
/************************************************/
if (nextToken('0', false) == null) //viewstate
nextToken('1', true);
nextToken(')', true);
nextToken(',', false);
}
newline();
}
}

/**
parse a place-block
*/
private void parse_places() throws NetParseException {
String Name, ID;
Member Place;

newline();
while (nextToken('|', false) != null) {
Name = nextToken(WORD, true); //name of Place
ID = "p" + nextToken(NUMBER, true); //ID of Place
Place = new Place((Net)theNet, Name, this, ID); // register new Place!!
newline();
parse_Extension(Place, "PLACE");
newline();
}
nextToken(';', true);
newline();
}

private String parse_StringCollection() throws NetParseException {
String valueOfSC = "";
while (nextToken('|', false) != null) {
if (valueOfSC.length() > 0) valueOfSC += "\n";
valueOfSC += nextToken(STRING, true); //concatinate String-Collection
newline();
}
return valueOfSC;
}

/**
parse a transition-block
*/
private void parse_transitions() throws NetParseException {
String Name, ID;
Member Transition;

newline();
while (nextToken('|', false) != null) {
Name = nextToken(WORD, true); //name of Transition
ID = "t" + nextToken(NUMBER, true); //ID of Transition
Transition = new Transition((Net)theNet, Name, this, ID); // register new Transition!!
newline();
parse_Extension(Transition, "TRANSITION");
newline();
}
nextToken(';', true);
newline();
}

private void restoreToken(int chr) {
restoredChars.insertElementAt(new Integer(chr), 0);
}

/***************************************************************
************************ lexer methods ************************
***************************************************************/

/*restoreToken-methods are used by nextToken*/
private void restoreToken(String str) {
for (int i = str.length() - 1; i >= 0; i--) {
restoredChars.insertElementAt(new Integer(str.charAt(i)), 0);
}
}

/**
Saves the given net (theNets) in a file specified by theURL
using the grammar of the file format used by the old pnk
python implementation.
*/
public void save(Vector theNets, URL theURL) {
theNet = (Net)theNets.elementAt(0);

try {
fileOut = new FileOutputStream(theURL.getFile()); // open output stream
try {
write_net(); // write the net into the output stream
fileOut.close(); // close output stream
} catch (IOException e) {
System.err.println("IOException occured while trying to save the net!!!");
}
} catch (FileNotFoundException e) {
System.err.println("Cannot write into '" + theURL.getFile() + "'!!!");
}
}

private void setExtension(Extendable netObject, String name, String value) {
try {
netObject.setExtension(this, name, value);
} catch (IllegalArgumentException e) {
System.err.println("Extension '" + name + "' not found! It will be ignored: continue loading!");
}
}

/* ************************************************************************************* */
/* ************** following methods are used to save a net as .net-File **************** */
/* ************************************************************************************* */

/*builds up a translation table for extensions (Java -> Python)
(see file: netTypeSpecifications/netTypesPytJava.table)*/
private String setExtensionTableJavaPyt(String netType) throws NetParseException {
String oldExt, newExt, block, oldNetType, newNetType = null;

try {
file = new FileInputStream(pytToJavaTable);
} catch (FileNotFoundException e) {
System.err.println("Pyt-Java-Translation-Table not found!");
return netType;
}
restoredChars = new Vector(10, 1);
line = 1;

/*start parsing translation file*/
do {
while (nextToken(LF, false) != null) {; }
oldNetType = nextToken(WORD, false);
if (oldNetType != null) {
newNetType = nextToken(WORD, true);
if (newNetType.compareTo(netType) != 0)
newNetType = null;
while (nextToken(LF, false) != null) {; }

while (nextToken(';', false) == null) {
block = nextToken(WORD, true); // block-name
while (nextToken(LF, false) != null) {; }
while (nextToken(';', false) == null) {
oldExt = nextToken(QUOTED_STRING, true); // old extension
newExt = nextToken(QUOTED_STRING, true); // new extension
if (newNetType != null)
insertExtTab(block, newExt, oldExt); // insert into extensionTable
while (nextToken(LF, false) != null) {; }
}
while (nextToken(LF, false) != null) {; }
}
while (nextToken(LF, false) != null) {; }
}
} while (oldNetType != null && newNetType == null);

if (oldNetType == null)
oldNetType = netType;

return oldNetType;
}

/*builds up a translation table for extensions (see file: netTypeSpecifications/
netTypesPytJava.table)*/
private String setExtensionTablePytJava(String netType) throws NetParseException {
InputStream oldFIStream = file;
Vector oldRestoredChars = restoredChars;
int oldLines = line;
String oldExt, newExt, block, oldNetType, newNetType = null;

try {
file = new FileInputStream(pytToJavaTable);
} catch (FileNotFoundException e) {
System.err.println("Pyt-Java-Translation-Table not found!");
file = oldFIStream;
return netType;
}
restoredChars = new Vector(10, 1);
line = 1;

/*start parsing translation file*/
do {
while (nextToken(LF, false) != null) {; }
oldNetType = nextToken(WORD, false);
if (oldNetType != null) {
if (oldNetType.compareTo(netType) == 0)
newNetType = nextToken(WORD, true);
else
nextToken(WORD, true);
while (nextToken(LF, false) != null) {; }

while (nextToken(';', false) == null) {
block = nextToken(WORD, true); // block-name
while (nextToken(LF, false) != null) {; }
while (nextToken(';', false) == null) {
oldExt = nextToken(QUOTED_STRING, true); // old extension
newExt = nextToken(QUOTED_STRING, true); // new extension
if (newNetType != null)
insertExtTab(block, oldExt, newExt); // insert into extensionTable
while (nextToken(LF, false) != null) {; }
}
while (nextToken(LF, false) != null) {; }
}
while (nextToken(LF, false) != null) {; }
}
} while (oldNetType != null && newNetType == null);

if (newNetType == null)
newNetType = netType;

file = oldFIStream;
restoredChars = oldRestoredChars;
line = oldLines;
return newNetType;
}

/*write the String str into the output stream (fileOut)*/
private void write(String str) throws IOException {
fileOut.write(str.getBytes());
}

/*write the arc block*/
private void write_arcs() throws IOException {
write("|ARCS");
nl();
Vector arcs = ((Net)theNet).getArcs();
for (int i = 0; i < arcs.size(); i++) {
Arc arc = (Arc)arcs.get(i);
/* write the new ID's for source, target and the arc itself */
write("|" + getNewId(arc.getSource()) + " --> " + getNewId(arc.getTarget()) + " " + getNewId(arc));
nl();
/*write arc inscription*/
write_StringCollection(arc.getExtension("inscription").toString());
write(";");
nl();
/* write arc extensions */
write_extensions(arc, "ARC");
write(";");
nl();
}
write(";");
nl();
}

/*write graphical information of arcs*/
private void write_edArcs() throws IOException {
write("ARC");
nl();
Vector arcs = ((Net)theNet).getArcs();
for (int i = 0; i < arcs.size(); i++) {
Arc arc = (Arc)arcs.get(i);
Vector pages = arc.getPages();
for (int j = 0; j < pages.size(); j++) {
int page = ((Integer)pages.get(j)).intValue(); // actual page
write(" " + getNewId(arc) + " :"); // write new ID of the arc
nl();
/**********************************/
/* dragpoint list not implemented */
/**********************************/
write(" " + page + " 0 0"); // numberOfSourceReference, numberOfTargetReference???
nl();
/* write graphical information of extensions */
write_objectExtensions(arc, page, "ARC");
write(" .");
nl();
}
}
write(";");
nl();
}

/*write editor infos*/
private void write_edNet() throws IOException {
write("EDITOR_INFOS");
nl();
write_edPages(); // write page information
write_edPlaces(); // write graphical information of places
write_edTransitions(); // write graphical information of transitions
write_edArcs(); // write graphical information of arcs
write("END_EDITOR");
nl();
}

/*write page information*/
private void write_edPages() throws IOException {
write("PAGES");
nl();
/************************************/
/* Page information not implemented */
/************************************/
write(";");
nl();
}

/*write graphical information of places*/
private void write_edPlaces() throws IOException {
write("PLACE");
nl();
Vector places = ((Net)theNet).getPlaces();
for (int i = 0; i < places.size(); i++) {
Place place = (Place)places.get(i);
Vector pages = place.getPages();
for (int j = 0; j < pages.size(); j++) {
int page = ((Integer)pages.get(j)).intValue(); // actual page
/*x- and y-coordinates on actual page*/
double x = Math.rint(place.getPosition(page).getX() / GRAPH_FACTOR);
double y = Math.rint(place.getPosition(page).getY() / GRAPH_FACTOR);
write(" " + getNewId(place) + " :"); // write new ID of the place
nl();
write(" " + page + " " + x + " " + y); // write page, x and y
nl();
/* write graphical information of extensions (optional)*/
if (!place.getExtIdToObject().isEmpty())
write_objectExtensions(place, page, "PLACE");
write(" .");
nl();
}
}
write(";");
nl();
}

/*write graphical information of transitions*/
private void write_edTransitions() throws IOException {
write("TRANSITION");
nl();
Vector transitions = ((Net)theNet).getTransitions();
for (int i = 0; i < transitions.size(); i++) {
Transition transition = (Transition)transitions.get(i);
Vector pages = transition.getPages();
for (int j = 0; j < pages.size(); j++) {
int page = ((Integer)pages.get(j)).intValue(); // actual page
/*x- and y-coordinates on actual page*/
double x = Math.rint(transition.getPosition(page).getX() / GRAPH_FACTOR);
double y = Math.rint(transition.getPosition(page).getY() / GRAPH_FACTOR);
write(" " + getNewId(transition) + " :"); // write new ID of the transition
nl();
write(" " + page + " " + x + " " + y); // write page, x and y
nl();
/* write graphical information of extensions (optional)*/
if (!transition.getExtIdToObject().isEmpty())
write_objectExtensions(transition, page, "TRANSITION");
write(" .");
nl();
}
}
write(";");
nl();
}

/*writes extensions of a netObject; type specifies the netObject
(PLACE/ARC/TRANSITION/NET(for global extensions))*/
private void write_extensions(Extendable netObject, String type) throws IOException {
Enumeration extNames = netObject.getExtIdToObject().keys();
while (extNames.hasMoreElements()) {
String actExtName = (String)extNames.nextElement();
Extension actExtension = netObject.getExtension(actExtName);
write("|" + javaExt2Pyt(actExtName, type)); // translate and write actual extension name
nl();
write_StringCollection(actExtension.toString()); // its value is a string collection
write(";");
nl();
}
}

/*write initial markings*/
private void write_marking() throws IOException {
write("|MARKING");
nl();
Vector places = ((Net)theNet).getPlaces();
for (int i = 0; i < places.size(); i++) {
Place place = (Place)places.get(i);
write("|" + getNewId(place)); // write the new ID of the place
nl();
/*the initial marking is a string collection*/
write_StringCollection(place.getExtension("initialMarking").toString());
write(";");
nl();
}
write(";");
nl();
}

/*This method is called by the save method. It writes the net (theNet) into
an open output stream (fileOut).*/
private void write_net() throws IOException {
write("|NET");
nl();
write("|" + theNet.getName()); // write net name
nl();
/* translate specification and build up hastable for extension translation */
String spec = null;
try {
spec = setExtensionTableJavaPyt(ac.getNetType(theNet));
} catch (NetParseException e) {
e.printStackTrace();
}
write("|SPECIFICATION " + spec); // write net specification
nl();
write_extensions(theNet, "NET"); //write global extensions
write_places(); // write place block
write_transitions(); // write transition block
write_arcs(); // write arc block
write_marking(); // write initial markings
write("|NET_END");
nl();
write_edNet(); // write editor infos
}

/* write graphical information of all extensions from member on page 'page' */
private void write_objectExtensions(Member member, int page, String type) throws IOException {
write(" {");
Enumeration extNames = member.getExtIdToObject().keys(); // get all extensions
while (extNames.hasMoreElements()) {
String actExtName = (String)extNames.nextElement();
Extension actExtension = member.getExtension(actExtName);
/*relative position (x- and y-coordinates)*/
long relX = Math.round(actExtension.getOffset(page).getX() / GRAPH_FACTOR);
long relY = Math.round(actExtension.getOffset(page).getY() / GRAPH_FACTOR);
/*write translated extension name, relative x and y and the view state;
view states not implemented yet (extensions are always visible)*/
write("'" + javaExt2Pyt(actExtName, type) + "': (" + relX + ", " + relY + ", 1)");
if (extNames.hasMoreElements())
write(", ");
}
write("}");
nl();
}

/*write the place block*/
private void write_places() throws IOException {
write("|PLACES");
nl();
Vector places = ((Net)theNet).getPlaces();
for (int i = 0; i < places.size(); i++) {
Place place = (Place)places.get(i);
/* write the name of the place (replace spaces by '_') and write the new ID*/
write("|" + place.getName().replace(' ', '_') + " " + getNewId(place));
nl();
/* write place extensions */
write_extensions(place, "PLACE");
write(";");
nl();
}
write(";");
nl();
}

/*write a string collection*/
private void write_StringCollection(String str) throws IOException {
if (str.length() == 0) { // an empty string collection
write("|");
nl();
return;
}

int index = str.indexOf(10); // the first line feed
while (index > 0) {
write("|");
write(str.substring(0, index));
nl();
if (index < str.length() - 1)
str = str.substring(index + 1, str.length());
else
str = "";
index = str.indexOf(10); // the next line feed
}
if (str.length() > 0) { // write the rest of the string collection
write("|");
write(str);
nl();
}
}

/*write the transition block*/
private void write_transitions() throws IOException {
write("|TRANSITIONS");
nl();
Vector transitions = ((Net)theNet).getTransitions();
for (int i = 0; i < transitions.size(); i++) {
Transition transition = (Transition)transitions.get(i);
/* write the name of the transition (replace spaces by '_') and write the new ID*/
write("|" + transition.getName().replace(' ', '_') + " " + getNewId(transition));
nl();
/* write transition extensions */
write_extensions(transition, "TRANSITION");
write(";");
nl();
}
write(";");
nl();
}
}
(12-12/17)