package com.jpaulmorrison.graphics;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import com.jpaulmorrison.graphics.DrawFBP.FileChooserParms;
import com.jpaulmorrison.graphics.DrawFBP.GenLang;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
public class CodeManager implements ActionListener, DocumentListener {
DrawFBP driver;
HashSet<String> portNames;
HashMap<String, Integer> blocklist;
// HashMap<String, Integer> portlist;
Style baseStyle, normalStyle, packageNameStyle, errorStyle,
quotedStringStyle, commentStyle;
JDialog dialog;
StyledDocument doc;
boolean changed = false;
boolean generated = false;
boolean packageNameChanged = false;
// String targetLang;
// final boolean SAVE_AS = true;
boolean error = false;
boolean fbpMode; // generating .fbp notation
String ext;
Diagram diag;
// Font font;
String packageName = null;
LinkedList<String> counterList = new LinkedList<String>();
JTextPane textPane;
JScrollPane scrollPane;
// GenLang compLang;
HashMap<Integer, String> descArray = new HashMap<Integer, String>();
// HashMap<Integer, String> cdescArray = new HashMap<Integer, String>();
// int type;
JLabel nsLabel = null;
boolean SAVE_AS = true;
FileChooserParms[] saveFCPArr;
//String langLabel;
GenLang gl = null;
String upPort = null;;
String dnPort = null;
CodeManager(Diagram d) {
diag = d;
driver = d.driver;
dialog = new JDialog(driver.frame);
driver.depDialog = dialog;
DrawFBP.applyOrientation(dialog);
// type = DrawFBP.GENCODE;
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent ev) {
Boolean res = true;
if (changed)
res = askAboutSaving();
if (res){
driver.depDialog = null;
dialog.dispose();
}
}
});
dialog.setJMenuBar(createMenuBar());
dialog.repaint();
BufferedImage image = driver.loadImage("DrawFBP-logo-small.png");
dialog.setIconImage(image);
Point p = driver.frame.getLocation();
Dimension dim = driver.frame.getSize();
dialog.setPreferredSize(new Dimension(dim.width - 100, dim.height - 50));
dialog.setLocation(p.x + 100, p.y + 50);
dialog.setForeground(Color.WHITE);
// jframe.setVisible(false);
dialog.pack();
StyleContext sc = new StyleContext();
doc = new DefaultStyledDocument(sc);
textPane = new JTextPane(doc);
scrollPane = new JScrollPane(textPane);
setStyles(sc);
dialog.setVisible(true);
textPane.setVisible(true);
scrollPane.setVisible(true);
dialog.add(scrollPane);
textPane.setFont(driver.fontf);
dialog.setFont(driver.fontf);
doc.addDocumentListener(this);
}
void genCode() {
if (!generateCode()) {
dialog.dispose();
}
}
boolean generateCode() {
fbpMode = false;
//langLabel = diag.diagLang.label;
gl = diag.diagLang;
// diag.targetLang = langLabel;
changed = true;
diag.fCPArr[DrawFBP.PROCESS] = driver.new FileChooserParms(
"Process", diag.diagLang.srcDirProp,
"Select " + diag.diagLang.showLangs()
+ " component from directory",
diag.diagLang.suggExtn, diag.diagLang.filter,
"Components: " + diag.diagLang.showLangs() + " "
+ diag.diagLang.showSuffixes());
diag.fCPArr[DrawFBP.GENCODE] = driver.new FileChooserParms(
"Generated code", diag.diagLang.netDirProp,
"Specify file name for generated code",
"." + diag.diagLang.suggExtn, diag.diagLang.filter,
diag.diagLang.label);
String component = (gl.label.equals("Java"))
? "component"
: "Component";
// String connect = (gl.label.equals("Java")) ? "connect" : "Connect";
String initialize = (gl.label.equals("Java"))
? "initialize"
: "Initialize";
String _port = (gl.label.equals("Java")) ? "port" : "Port";
String sDO = (gl.label.equals("Java"))
? "setDropOldest()"
: "SetDropOldest()";
String fn = diag.diagFile == null ? "unknown" : diag.diagFile.getName();
dialog.setTitle("Generated Code for " + fn);
dialog.setJMenuBar(createMenuBar());
BufferedImage image = driver.loadImage("DrawFBP-logo-small.png");
dialog.setIconImage(image);
String code = "";
// boolean error = false;
portNames = new HashSet<String>();
blocklist = new HashMap<String, Integer>();
ext = "Network";
Style[] styles = new Style[20];
for (Block block : diag.blocks.values()) {
if (block instanceof ExtPortBlock) {
ext = "SubNet";
if (block.description == null || block.description.equals("")) {
block.description = "IN/OUT";
block.description = makeUniqueDesc(block.description);
}
}
}
if (gl.label.equals("Java")) {
packageName = driver.properties.get("currentPackageName");
if (packageName == null) {
packageName = "xxxxxx";
//packageName = (String) MyOptionPane.showInputDialog(dialog,
// "Please fill in a package/namespace name", null);
//packageName = packageName.trim();
//driver.properties.put("currentPackageName", packageName);
//driver.propertiesChanged = true;
}
}
String[] contents;
if (gl.label.equals("JSON")) {
contents = new String[1];
contents[0] = generateJSON();
styles[0] = normalStyle;
} else {
contents = new String[20];
if (gl.label.equals("Java")) {
contents[0] = "package ";
contents[1] = packageName + ";";
} else
contents[0] = "namespace {";
contents[2] = " // change this if you want \n";
if (gl.label.equals("Java"))
contents[2] += "import com.jpaulmorrison.fbp.core.engine.*; \n";
if (ext.equals("SubNet"))
contents[3] = genMetadata(gl.label) + "\n";
else
contents[3] = "";
contents[4] = "public class ";
contents[5] = diag.title;
if (gl.label.equals("Java"))
contents[6] = " extends ";
else
contents[6] = " : ";
contents[7] = ext;
if (gl.label.equals("Java"))
contents[8] = " {\nString description = ";
else
contents[8] = " {\nstring description = ";
if (diag.desc == null)
diag.desc = " ";
contents[9] = "\"" + diag.desc + "\"";
if (gl.label.equals("Java"))
contents[10] = ";\nprotected void define() { \n";
else
contents[10] = ";\npublic override void Define() { \n";
styles[0] = normalStyle;
styles[1] = packageNameStyle;
styles[2] = baseStyle;
styles[3] = packageNameStyle;
styles[4] = normalStyle;
styles[5] = packageNameStyle;
styles[6] = normalStyle;
styles[7] = packageNameStyle;
styles[8] = normalStyle;
styles[9] = packageNameStyle;
styles[10] = normalStyle;
for (Block block : diag.blocks.values()) {
String t;
if (block instanceof ProcessBlock) {
if (block.description == null) {
MyOptionPane.showMessageDialog(driver.frame,
"One or more missing block descriptions", MyOptionPane.WARNING_MESSAGE);
error = true;
return false;
}
String s = cleanDesc(block);
String c = null;
if (block.javaClass != null) {
c = cleanComp(block);
if (c.toLowerCase().endsWith(".class"))
c = c.substring(0, c.length() - 6);
}
else
c = "Invalid class";
descArray.put(new Integer(block.id), s);
if (!block.multiplex)
code += " " + genComp(s, c, gl.label) + "; \n";
else {
if (block.mpxfactor == null) {
String d = (String) MyOptionPane.showInputDialog(
driver.frame,
"Multiplex factor for " + "\""
+ block.description + "\"",
"Please enter number");
if (d == null || d.equals("")) {
block.mpxfactor = "????";
error = true;
} else
block.mpxfactor = d;
diag.changed = true;
}
dialog.repaint();
if (block.mpxfactor != null) {
code += "int " + compress(s) + "_count = "
+ block.mpxfactor + "; "
+ " // multiplex counter for " + "\""
+ s + "\"\n";
}
code += "for (int i = 0; i < " + compress(s)
+ "_count; i++)\n";
// code += component + "(\"" + s + ":\" + i, " + c +
// "); ";
code += " " + genCompMpx(s, c, gl.label) + "; ";
if (c.equals("????")) {
code += " // <=== fill in component name";
}
code += "\n";
}
}
if (block instanceof ExtPortBlock) {
ExtPortBlock eb = (ExtPortBlock) block;
String s = "";
if (block.type.equals(Block.Types.EXTPORT_IN_BLOCK)) {
s = "SUBIN";
if (eb.substreamSensitive)
t = "SubInSS";
else
t = "SubIn";
} else
if (block.type.equals(Block.Types.EXTPORT_OUT_BLOCK)) {
s = "SUBOUT";
if (eb.substreamSensitive)
t = "SubOutSS";
else
t = "SubOut";
} else {
s = "SUBOI";
t = "SubOI";
}
s = makeUniqueDesc(s); // and make it unique
// if (!(t.toLowerCase().endsWith(".class")))
// t += ".class";
if (t.toLowerCase().endsWith(".class"))
t = t.substring(0, t.length() - 6);
code += " " + genComp(s, t, gl.label) + "; \n";
code += " " + initialize + "(\"" + eb.description + "\", " + component + "(\""
+ s + "\"), " + _port + "(\"NAME\")); \n";
}
if (block instanceof IIPBlock)
descArray.put(new Integer(block.id), block.description);
}
for (Arrow arrow : diag.arrows.values()) {
// generate a connection or initialize
Block from = diag.blocks.get(new Integer(arrow.fromId));
Arrow a2 = arrow.findArrowEndingAtBlock();
if (a2 == null)
continue;
Block to = diag.blocks.get(new Integer(a2.toId));
if (to == null) {
MyOptionPane.showMessageDialog(driver.frame,
"Downstream block not found: from " + from.description, MyOptionPane.ERROR_MESSAGE);
break;
}
if (from == null || to == null || from instanceof FileBlock
|| from instanceof ReportBlock
|| from instanceof LegendBlock
|| to instanceof FileBlock || to instanceof ReportBlock
|| to instanceof LegendBlock)
continue;
if (!getPortNames(arrow))
return false;
dialog.repaint();
String fromDesc = descArray.get(new Integer(arrow.fromId));
// String cFromDesc = cdescArray.get(new Integer(arrow.fromId));
String toDesc = descArray.get(new Integer(a2.toId));
// String cToDesc = cdescArray.get(new Integer(a2.toId));
// boolean ok;
// }
dialog.repaint();
// String upPort = arrow.upStreamPort;
// String dnPort = a2.downStreamPort;
String cap = "";
if (arrow.capacity > 0)
cap = ", " + arrow.capacity;
if (from instanceof ProcessBlock
&& to instanceof ProcessBlock) {
if (!arrow.endsAtLine && checkDupPort(dnPort, to)) {
String proc = to.description;
MyOptionPane.showMessageDialog(driver.frame,
"Duplicate port name: " + proc + "." + dnPort, MyOptionPane.ERROR_MESSAGE);
error = true;
}
if (checkDupPort(upPort, from)) {
String proc = from.description;
MyOptionPane.showMessageDialog(driver.frame,
"Duplicate port name: " + proc + "." + upPort, MyOptionPane.ERROR_MESSAGE);
error = true;
}
if (from.multiplex) {
code += "for (int i = 0; i < " + compress(fromDesc)
+ "_count; i++)\n";
code += " " + genConnect(arrow) + "(" + component + "(\""
+ fromDesc + ":\" + i), " + _port + "("
+ q(upPort) + "), " + component + "(\"" + toDesc
+ "\"), " + _port + "(" + q(dnPort) + ")" + cap
+ "); \n";
if (arrow.dropOldest)
code += "c" + arrow.id + "." + sDO + "; \n";
} else if (to.multiplex) {
code += "for (int i = 0; i < " + compress(toDesc)
+ "_count; i++)\n";
code += " " + genConnect(arrow) + "(" + component + "("
+ q(fromDesc) + "), " + _port + "(" + q(upPort)
+ ",i), " + component + "(\"" + toDesc
+ ":\" + i), " + _port + "(" + q(dnPort) + ")"
+ cap + "); \n";
if (arrow.dropOldest)
code += "c" + arrow.id + "." + sDO + "; \n";
} else {
code += " " + genConnect(arrow) + "(" + component + "("
+ q(fromDesc) + "), " + _port + "(" + q(upPort)
+ "), " + component + "(\"" + toDesc + "\"), "
+ _port + "(" + q(dnPort) + ")" + cap + "); \n";
if (arrow.dropOldest)
code += "c" + arrow.id + "." + sDO + "; \n";
}
}
else
if (from instanceof IIPBlock
&& to instanceof ProcessBlock) {
if (!arrow.endsAtLine && checkDupPort(dnPort, to)) {
String proc = to.description;
MyOptionPane.showMessageDialog(driver.frame,
"Duplicate port name: " + proc + "." + dnPort, MyOptionPane.ERROR_MESSAGE);
error = true;
}
code += " " + initialize + "(" + q(fromDesc) + ", " + component
+ "(\"" + toDesc + "\"), " + _port + "(" + q(dnPort)
+ ")" + cap + "); \n";
}
if (from instanceof ExtPortBlock) {
code += " " + genConnect(arrow) + "(" + component + "("
+ q(fromDesc) + "), " + _port + "(\"OUT\"), "
+ component + "(\"" + toDesc + "\"), " + _port + "("
+ q(dnPort) + ")" + cap + "); \n";
if (arrow.dropOldest)
code += "c" + arrow.id + "." + sDO + "; \n";
} else if (to instanceof ExtPortBlock) {
code += " " + genConnect(arrow) + "(" + component + "("
+ q(fromDesc) + "), " + _port + "(" + q(upPort)
+ "), " + component + "(\"" + toDesc + "\"), "
+ _port + "(\"IN\" " + ")" + cap + "); \n";
if (arrow.dropOldest)
code += "c" + arrow.id + "." + sDO + "; \n";
}
}
if (ext.equals("Network")) {
String s = diag.title;
int i = s.indexOf(".");
if (i > -1)
s = s.substring(0, i);
code += "} \n";
if (gl.label.equals("Java"))
code += "public static void main(String[] argv) throws Exception { \n"
+ " new " + s + "().go(); \n";
else
code += "internal static void main(String[] argv) { \n"
+ " new " + s + "().Go();\n }\n";
}
code += "} \n";
int sno = 11;
contents[sno] = code;
styles[sno] = normalStyle;
sno++;
contents[sno] = "}\n";
styles[sno] = normalStyle;
sno++;
if (error) {
contents[sno] = "\n /* Errors in generated code - they must be corrected for your program to run - \n\n"
+ " remove this comment when you are done */";
styles[sno] = errorStyle;
MyOptionPane.showMessageDialog(driver.frame,
"Error in generated code", MyOptionPane.ERROR_MESSAGE);
}
}
// insert data from arrays
try {
for (int i = 0; i < contents.length; i++) {
if (contents[i] != null)
doc.insertString(doc.getLength(), contents[i], styles[i]);
}
} catch (BadLocationException ble) {
MyOptionPane.showMessageDialog(driver.frame,
"Couldn't insert text into text pane", MyOptionPane.ERROR_MESSAGE);
return false;
}
// if (diag.compLang != glcompLang)
// diag.compLang = compLang;
changed = true;
colourCode();
generated = true;
nsLabel.setText("Not saved");
dialog.repaint();
// jframe.update(jdriver.osg);
return true;
}
String genComp(String name, String className, String lang) {
if (className == null)
className = "????";
if (lang.equals("Java")) {
if (!(className.equals("Invalid class")))
className += ".class";
return "component(\"" + name + "\"," + className + ")";
}
else
return "Component(\"" + name + "\", typeof(" + className + "))";
}
String genConnect(Arrow arrow) {
String connect = (gl.label.equals("Java")) ? "connect" : "Connect";
if (arrow.dropOldest) {
connect = "Connection c" + arrow.id + " = " + connect;
}
return connect;
}
String genCompMpx(String name, String className, String lang) {
if (className == null)
className = "????";
if (lang.equals("Java"))
return "component(\"" + name + ":\" + i," + className + ".class)";
else
return "Component(\"" + name + ":\" + i, typeof(" + className
+ "))";
}
void display(File file, GenLang gl) {
dialog.setTitle("Displayed Code: " + file.getName());
// genLang = gl;
String fileString = driver.curDiag.readFile(file);
if (fileString == null) {
MyOptionPane.showMessageDialog(driver.frame,
"Couldn't read file: " + file.getAbsolutePath(), MyOptionPane.ERROR_MESSAGE);
return;
}
// changed = false;
//if (file.getName().endsWith(".fbp")) {
nsLabel.setText("Not changed");
fbpMode = true;
changed = false;
//}
String suff = driver.curDiag.getSuffix(file.getName());
if (suff != null && suff.toLowerCase().equals("java")) {
int i = fileString.indexOf("package ");
if (i == -1) {
packageName = (String) MyOptionPane.showInputDialog(driver.frame,
"Missing package name - please specify package name",
null);
// driver.properties.put("currentPackageName", packageName);
// driver.propertiesChanged = true;
fileString = "package " + packageName + ";\n" + fileString;
changed = true;
} else {
int k = fileString.indexOf(";", i);
packageName = fileString.substring(i + 8, k);
}
packageName = packageName.trim();
String pkg = (String) driver.properties.get("currentPackageName");
if (pkg != null && !(pkg.equals(packageName))) {
driver.properties.put("currentPackageName", packageName);
driver.propertiesChanged = true;
}
}
try {
doc.insertString(0, fileString, normalStyle);
} catch (BadLocationException ble) {
MyOptionPane.showMessageDialog(driver.frame,
"Couldn't insert text into text pane", MyOptionPane.ERROR_MESSAGE);
return;
}
colourCode();
// if (file.getName().endsWith(".fbp"))
// type = DrawFBP.DIAGRAM;
dialog.repaint();
// frame.repaint();
return;
}
String genMetadata(String lang) {
String inData = "";
String outData = "";
String descr = " ";
if (diag.desc != null && !(diag.desc.equals(" "))) {
if (lang.equals("Java"))
descr = "@ComponentDescription(\"" + diag.desc + "\") \n";
else
descr = "[ComponentDescription(\"" + diag.desc + "\")] \n";
}
int ins = 0;
int outs = 0;
for (Block block : diag.blocks.values()) {
if (block instanceof ExtPortBlock) {
if (block.type.equals(Block.Types.EXTPORT_IN_BLOCK)) {
if (lang.equals("Java")) {
ins++;
inData += ", @InPort(\"" + block.description + "\")";
} else {
inData += "[InPort(\"" + block.description + "\")] \n";
}
} else if (block.type.equals(Block.Types.EXTPORT_OUT_BLOCK)) {
if (lang.equals("Java")) {
outs++;
outData += ", @OutPort(\"" + block.description + "\")";
} else {
outData += "[OutPort(\"" + block.description
+ "\")] \n";
}
}
}
}
if (lang.equals("Java")) {
if (!inData.equals("")) {
inData = inData.substring(2);
if (ins > 1)
inData = "@InPorts({" + inData + "})";
inData += "\n";
}
if (!outData.equals("")) {
outData = outData.substring(2);
if (outs > 1)
outData = "@OutPorts({" + outData + "})";
outData += "\n";
}
}
return descr + inData + outData;
}
String makeUniqueDesc(String s) {
Integer i;
String t = s;
if (blocklist.containsKey(s)) {
i = blocklist.get(s);
i = new Integer(i.intValue() + 1);
t = s + "_" + i.toString() + "_";
} else
i = new Integer(1);
blocklist.put(s, i);
return t;
}
String makeUniquePort(String s, Block b) {
Integer i;
String t = s;
if (b.portlist == null)
b.portlist = new HashMap<String, Integer>();
if (b.portlist.containsKey(s)) {
i = b.portlist.get(s);
i = new Integer(i.intValue() + 1);
t = s + "_" + i.toString() + "_";
} else
i = new Integer(1);
b.portlist.put(s, i);
return t;
}
boolean checkDupPort(String port, Block bl) {
// return false if no duplication
String s = port + ":" + bl.id;
if (portNames.contains(s))
return true;
portNames.add(s);
return false;
}
void setStyles(StyleContext sc) {
Font font = driver.fontf;
// baseStyle = new SimpleAttributeSet();
Style defaultStyle = sc.getStyle(StyleContext.DEFAULT_STYLE);
baseStyle = sc.addStyle(null, defaultStyle);
int s = font.getSize();
StyleConstants.setSpaceAbove(baseStyle, 4);
StyleConstants.setSpaceBelow(baseStyle, 4);
StyleConstants.setForeground(baseStyle, Color.DARK_GRAY);
StyleConstants.setFontFamily(baseStyle, font.getFamily());
StyleConstants.setFontSize(baseStyle, s);
normalStyle = sc.addStyle(null, baseStyle);
StyleConstants.setForeground(normalStyle, Color.BLUE);
// StyleConstants.setFontSize(normalStyle, s);
packageNameStyle = sc.addStyle(null, baseStyle);
StyleConstants.setForeground(packageNameStyle, Color.MAGENTA);
// StyleConstants.setFontSize(packageNameStyle, s);
errorStyle = sc.addStyle(null, baseStyle);
StyleConstants.setForeground(errorStyle, Color.RED);
// StyleConstants.setFontSize(errorStyle, s);
quotedStringStyle = sc.addStyle(null, baseStyle);
StyleConstants.setForeground(quotedStringStyle, new Color(178, 34, 34));// Firebrick
// StyleConstants.setFontSize(quotedStringStyle, s);
commentStyle = sc.addStyle(null, baseStyle);
StyleConstants.setForeground(commentStyle, new Color(46, 139, 87));// Sea
// green
// StyleConstants.setFontSize(commentStyle, s);
}
void colourCode() {
boolean packageRead = false;
for (int i = 0; i < doc.getLength(); i++)
try {
if (!packageRead && doc.getText(i, 8).equals("package ")) {
packageRead = true;
i += 8;
int j = doc.getText(i, doc.getLength() - 9).indexOf(";");
doc.setCharacterAttributes(i, j, packageNameStyle, false); // Magenta
}
if (doc.getText(i, 4).equals("????"))
doc.setCharacterAttributes(i, 4, errorStyle, false); // Red
if (doc.getText(i, 10).equals("null.class"))
doc.setCharacterAttributes(i, 10, errorStyle, false); // Red
if (doc.getText(i, 1).equals("@")) {
int j;
for (j = i; j < doc.getLength(); j++) {
if (doc.getText(j, 1).equals("\n"))
break;
}
doc.setCharacterAttributes(i, j - i, packageNameStyle,
false); // Magenta
}
if (doc.getText(i, 1).equals("\"")
&& !(doc.getText(i - 1, 1).equals(File.separator))) {
int j = i + 1;
for (; j < doc.getLength(); j++) {
if (doc.getText(j, 1).equals("\"") && !(doc
.getText(j - 1, 1).equals(File.separator)))
break;
}
doc.setCharacterAttributes(i, j - i + 1, quotedStringStyle,
false); // firebrick
i = j; // skip quoted string
}
if (doc.getText(i, 2).equals("/*")) {
int j = i + 2;
for (; j < doc.getLength(); j++) {
if (doc.getText(j, 2).equals("*/"))
break;
}
doc.setCharacterAttributes(i, j - i + 2, commentStyle,
false); // green
i = j + 2; // skip comment
}
if (doc.getText(i, 2).equals("//")) {
int j = i + 2;
String ls = "\n";
for (; j < doc.getLength(); j++) {
if (doc.getText(j, ls.length()).equals(ls))
break;
// String x = doc.getText(j, ls.length());
// x += "";
}
doc.setCharacterAttributes(i, j - i + 1, commentStyle,
false); // green
i = j + ls.length(); // skip line separator
}
if (doc.getText(i, 3).equals("<==")) {
int j = i + 3;
for (; j < doc.getLength(); j++) {
if (doc.getText(j, 1).equals("\n"))
break;
}
doc.setCharacterAttributes(i, j - i, baseStyle, false); // Gray
}
} catch (BadLocationException e) {
}
textPane.setFont(driver.fontf);
scrollPane.setFont(driver.fontf);
dialog.setFont(driver.fontf);
}
public void actionPerformed(ActionEvent e) {
String s = e.getActionCommand();
// if (s.equals("Save")) {
// saveCode(/*!SAVE_AS*/);
// } else
if (s.equals("Save As")) {
saveCode(/* SAVE_AS */);
} else if (s.equals("Exit")) {
Boolean res = true;
if (changed)
res = askAboutSaving();
if (res)
dialog.dispose();
}
return;
}
public boolean askAboutSaving() {
int answer = MyOptionPane.showConfirmDialog(driver.frame,
"Save generated or modified code?", "Save code",
MyOptionPane.YES_NO_CANCEL_OPTION);
boolean b;
if (answer == MyOptionPane.YES_OPTION) {
// User clicked YES.
b = saveCode(/* SAVE_AS */);
// diag.diagLang = gl;
return b;
}
b = (answer == MyOptionPane.NO_OPTION);
// diag.diagLang = gl;
return b;
}
public void changedUpdate(DocumentEvent e) {
//Document doc = e.getDocument();
//String s = null;
//try {
// s = doc.getText(e.getOffset(), e.getLength());
//} catch (BadLocationException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
//}
//if (e.getOffset() > 0)
// changed = true;
if (packageName != null) {
if (e.getOffset() >= 8 && e.getOffset() <= 8 + packageName.length()
&& generated) {
packageNameChanged = true;
changed = true;
}
}
nsLabel.setText(changed ? "Not saved" : " ");
dialog.repaint();
}
public void insertUpdate(DocumentEvent e) {
if (e.getOffset() > 0)
changed = true;
if (packageName != null) {
if (e.getOffset() >= 8 && e.getOffset() <= 8 + packageName.length()
&& generated) {
packageNameChanged = true;
}
}
nsLabel.setText(changed ? "Not saved" : " ");
dialog.repaint();
}
public void removeUpdate(DocumentEvent e) {
if (e.getOffset() > 0)
changed = true;
if (packageName != null) {
if (e.getOffset() >= 8 && e.getOffset() <= 8 + packageName.length()
&& generated) {
packageNameChanged = true;
}
}
nsLabel.setText(changed ? "Not saved" : " ");
dialog.repaint();
}
String compress(String s) {
if (counterList.indexOf(s) == -1)
counterList.add(s);
return "X$" + counterList.indexOf(s);
}
boolean saveCode( /* boolean saveAs */) {
String fileString = null;
try {
fileString = doc.getText(0, doc.getLength());
} catch (BadLocationException ble) {
MyOptionPane.showMessageDialog(driver.frame,
"Couldn't get text from text pane", MyOptionPane.ERROR_MESSAGE);
// diag.changeCompLang();
return false;
}
File file = null;
// if (diag.genCodeFileName != null)
// file = new File(diag.genCodeFileName);
// if (file == null)
// saveAs = true;
// if (saveAs)
file = null;
if (diag.fCPArr[DrawFBP.GENCODE].fileExt.equals(".java")) {
try {
String t = doc.getText(0, doc.getLength());
int i = t.indexOf("package");
if (i > -1) {
int j = t.indexOf(";", i);
if (j > -1) {
String s = doc.getText(i + 8, j - i - 8);
s = s.trim();
if (packageName != null && !(packageName.equals(s))) {
packageName = s;
driver.properties.put("currentPackageName",
packageName);
driver.propertiesChanged = true;
MyOptionPane.showMessageDialog(driver.frame,
"Package name changed: " + packageName);
}
}
}
} catch (BadLocationException ble) {
ble.printStackTrace();
}
}
file = diag.genSave(file, diag.fCPArr[DrawFBP.GENCODE], fileString);
if (file == null) {
// MyOptionPane.showMessageDialog(driver.frame, "File not saved");
// diag.changeCompLang();
return false;
}
//MyOptionPane.showMessageDialog(driver.frame, "File " + file.getName() + " saved");
// genCodeFileName = file.getAbsolutePath();
driver.properties.put(diag.diagLang.netDirProp, file.getParent());
driver.propertiesChanged = true;
changed = false;
if (packageNameChanged) {
driver.properties.put("packageName", packageName);
driver.propertiesChanged = true;
}
// diag.targetLang = gl.label;
nsLabel.setText(changed ? "Not saved" : " ");
// diag.genCodeFileName = file.getAbsolutePath();
dialog.setTitle("Generated Code: " + file.getName());
dialog.repaint();
return true;
}
public JMenuBar createMenuBar() {
JMenuBar menuBar;
// Create the menu bar.
menuBar = new JMenuBar();
menuBar.setBorderPainted(true);
// Box box = new Box(BoxLayout.X_AXIS);
// box.setLayout(new FlowLayout(FlowLayout.LEFT));
JMenuItem menuItem =
/*
* new JMenuItem("Save"); menuBar.add(menuItem);
* menuItem.addActionListener(this); menuItem.setBorderPainted(true);
* menuItem =
*/
new JMenuItem("Save As");
menuBar.add(menuItem);
menuItem.addActionListener(this);
menuItem.setBorderPainted(true);
menuItem = new JMenuItem("Exit");
menuBar.add(menuItem);
menuItem.addActionListener(this);
menuItem.setBorderPainted(true);
// menuBar.add(box);
// int w = frame.getWidth();
menuBar.add(Box.createHorizontalStrut(200));
JPanel p = new JPanel();
nsLabel = new JLabel("Not changed");
p.add(nsLabel, BorderLayout.LINE_END);
menuBar.add(p, BorderLayout.LINE_END);
nsLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
nsLabel.setBackground(Color.WHITE);
return menuBar;
}
String generateJSON() {
String data;
data = "{\n\"properties\": {\n\"name\": ";
data += q(diag.title) + "\n},\n";
data += "\"processes\": {\n";
portNames = new HashSet<String>();
blocklist = new HashMap<String, Integer>();
String comma = "";
for (Block block : diag.blocks.values()) {
// String s = "";
if (block instanceof ProcessBlock && block.description == null) {
MyOptionPane.showMessageDialog(driver.frame,
"One or more missing block descriptions", MyOptionPane.WARNING_MESSAGE);
// error = true;
return null;
}
if (block instanceof ProcessBlock) {
String s = cleanDesc(block);
String t = cleanComp(block);
data += comma + q(s) + ":{ \"component\" :" + q(t)
+ ", \"display\": { \"x\":" + block.cx + ", \"y\":"
+ block.cy + "}}";
comma = "\n,";
descArray.put(new Integer(block.id), s);
}
// cdescArray.put(new Integer(block.id), block.description);
if (block instanceof IIPBlock) {
descArray.put(new Integer(block.id), block.description);
}
}
data += "\n},\n \"connections\": [\n";
comma = "";
for (Arrow arrow : diag.arrows.values()) {
// generate a connection or initialize
Block from = diag.blocks.get(new Integer(arrow.fromId));
Arrow a2 = arrow.findArrowEndingAtBlock();
Block to = diag.blocks.get(new Integer(a2.toId));
if (to == null) {
MyOptionPane.showMessageDialog(driver.frame,
"Downstream block not found: from " + from.description, MyOptionPane.ERROR_MESSAGE);
break;
}
if (from == null || to == null || from instanceof FileBlock
|| from instanceof ReportBlock
|| from instanceof LegendBlock || to instanceof FileBlock
|| to instanceof ReportBlock || to instanceof LegendBlock)
continue;
if (!getPortNames(arrow))
return "";
String fromDesc = descArray.get(new Integer(arrow.fromId));
// String cFromDesc = cdescArray.get(new Integer(arrow.fromId));
String toDesc = descArray.get(new Integer(a2.toId));
dialog.repaint();
if (!(from instanceof ProcessBlock) && !(from instanceof IIPBlock)
|| !(to instanceof ProcessBlock))
continue;
data += comma + "{ ";
// String upPort = arrow.upStreamPort;
// String dnPort = a2.downStreamPort;
if (upPort != null) {
upPort = upPort.toLowerCase();
upPort = makeUniquePort(upPort, from);
}
dnPort = dnPort.toLowerCase();
if (a2.dspMod == null)
a2.dspMod = makeUniquePort(dnPort, to);
// upPort = arrow.uspMod;
dnPort = a2.dspMod;
if (from instanceof IIPBlock) {
if (!arrow.endsAtLine && checkDupPort(dnPort, to)) {
String proc = to.description;
MyOptionPane.showMessageDialog(driver.frame,
"Duplicate port name: " + proc + "." + dnPort, MyOptionPane.ERROR_MESSAGE);
error = true;
}
data += "\"data\":" + q(fromDesc) + ",\n";
} else
data += "\"src\": {\n \"process\" :" + q(fromDesc)
+ ",\n\"port\":" + q(upPort) + "\n},";
data += "\"tgt\": {\n \"process\" :" + q(toDesc) + ",\n\"port\":"
+ q(dnPort) + "}\n}";
comma = "\n,";
}
data += "\n]\n}";
return data;
}
boolean genFbpCode() {
String code = "";
String cma = "";
// generated = false;
portNames = new HashSet<String>();
blocklist = new HashMap<String, Integer>();
// portlist = new HashMap<String, Integer>();
// diag.targetLang = "FBP";
saveFCPArr = diag.fCPArr;
// gl = diag.diagLang;
gl = driver.findGLFromLabel("FBP");
fbpMode = true;
diag.fCPArr[DrawFBP.GENCODE] = driver.new FileChooserParms(
"Generated code",
"currentFBPNetworkDir", "Specify file name for generated code",
".fbp", diag.diagLang.filter, "fbp");
for (Block block : diag.blocks.values()) {
if (block instanceof ProcessBlock) {
if (block.description == null) {
MyOptionPane.showMessageDialog(driver.frame,
"One or more missing block descriptions", MyOptionPane.ERROR_MESSAGE);
error = true;
return false;
}
String s = cleanDesc(block);
// String s = cleanComp(block);
code += cma + s + "(" + s + ")";
cma = ",\n";
descArray.put(new Integer(block.id), s);
// cdescArray.put(new Integer(block.id), s);
}
if (block instanceof IIPBlock) {
descArray.put(new Integer(block.id), block.description);
}
}
for (Arrow arrow : diag.arrows.values()) {
Block from = diag.blocks.get(new Integer(arrow.fromId));
Arrow a2 = arrow.findArrowEndingAtBlock();
Block to = diag.blocks.get(new Integer(a2.toId));
if (to == null) {
MyOptionPane.showMessageDialog(driver.frame,
"Downstream block not found", MyOptionPane.ERROR_MESSAGE);
break;
}
if (from == null || to == null || from instanceof FileBlock
|| from instanceof ReportBlock
|| from instanceof LegendBlock || to instanceof FileBlock
|| to instanceof ReportBlock || to instanceof LegendBlock)
continue;
if (!getPortNames(arrow))
return false;
String fromDesc = descArray.get(new Integer(arrow.fromId));
// String cFromDesc = cdescArray.get(new Integer(arrow.fromId));
String toDesc = descArray.get(new Integer(a2.toId));
// String cToDesc = cdescArray.get(new Integer(a2.toId));
dialog.repaint();
if (!(from instanceof IIPBlock)) {
upPort = arrow.upStreamPort;
upPort = upPort.replaceAll("-", "\\\\-");
upPort = upPort.replaceAll("\\.", "\\\\.");
upPort = makeUniquePort(upPort, from);
}
dnPort = a2.downStreamPort;
// dnPort = dnPort.toLowerCase();
if (a2.dspMod == null)
a2.dspMod = makeUniquePort(dnPort, to);
dnPort = a2.dspMod.replaceAll("-", "\\\\-");
dnPort = dnPort.replaceAll("\\.", "\\\\.");
if (from instanceof ProcessBlock
&& to instanceof ProcessBlock) {
if (!arrow.endsAtLine && checkDupPort(dnPort, to)) {
String proc = to.description;
MyOptionPane.showMessageDialog(driver.frame,
"Duplicate port name: " + proc + "." + dnPort, MyOptionPane.ERROR_MESSAGE);
error = true;
}
if (checkDupPort(upPort, from)) {
String proc = from.description;
MyOptionPane.showMessageDialog(driver.frame,
"Duplicate port name: " + proc + "." + upPort, MyOptionPane.ERROR_MESSAGE);
error = true;
}
if (from.multiplex) {
MyOptionPane.showMessageDialog(driver.frame,
"Multiplexing not supported", MyOptionPane.ERROR_MESSAGE);
error = true;
} else if (to.multiplex) {
MyOptionPane.showMessageDialog(driver.frame,
"Multiplexing not supported", MyOptionPane.ERROR_MESSAGE);
error = true;
} else
code += cma + fromDesc + " " + upPort + " -> " + dnPort
+ " " + toDesc;
} else
if (from instanceof IIPBlock && to instanceof ProcessBlock) {
if (!arrow.endsAtLine && checkDupPort(dnPort, to)) {
String proc = to.description;
MyOptionPane.showMessageDialog(driver.frame,
"Duplicate port name: " + proc + "." + dnPort, MyOptionPane.ERROR_MESSAGE);
error = true;
}
code += cma + "'" + fromDesc + "' -> " + dnPort + " " + toDesc;
}
if (from instanceof ExtPortBlock) {
code += cma + fromDesc + " out -> " + dnPort + " " + toDesc;
} else if (to instanceof ExtPortBlock) {
code += cma + fromDesc + " -> in " + toDesc;
}
}
// insert string data
try {
doc.insertString(doc.getLength(), code, baseStyle);
} catch (BadLocationException ble) {
MyOptionPane.showMessageDialog(driver.frame,
"Couldn't insert text into text pane", MyOptionPane.ERROR_MESSAGE);
// restore old language parameters
diag.fCPArr[DrawFBP.GENCODE] = driver.new FileChooserParms(
"Generated code",
diag.diagLang.netDirProp,
"Specify file name for generated code",
"." + diag.diagLang.suggExtn, diag.diagLang.filter,
diag.diagLang.label);
return false;
}
changed = true;
// colourCode();
generated = true;
nsLabel.setText(changed ? "Not saved" : " ");
dialog.repaint();
// jframe.update(jdriver.osg);
// restore old language parameters
diag.fCPArr[DrawFBP.GENCODE] = driver.new FileChooserParms(
"Generated code",
diag.diagLang.netDirProp,
"Specify file name for generated code",
"." + diag.diagLang.suggExtn, diag.diagLang.filter,
diag.diagLang.label);
return true;
}
String q(String s) {
return "\"" + s + "\"";
}
String cleanComp(Block b) {
// String[] sa = new String[2]; // process name and component name,
// resp.
// if (gl.label.equals("FBP"))
// s = cleanDesc(s); // clean up name
error = false;
String c = b.fullClassName;
if (c == null) {
c = b.codeFileName;
if (c == null) {
MyOptionPane.showMessageDialog(driver.frame,
"Missing full class name for: " + b.description, MyOptionPane.ERROR_MESSAGE);
error = true;
}
}
if (!error) {
/*
* if (gl.label.equals("JSON")) { // bit of a hack... int i =
* c.lastIndexOf(File.separator); if (i == -1) i =
* c.lastIndexOf("/"); c = c.substring(i + 1); int j =
* c.lastIndexOf("."); if (j > -1) c = c.substring(0, j); }
*/
int i = c.indexOf("!");
if (i > -1 && i < c.length() - 1)
c = c.substring(i + 1);
if (c.toLowerCase().endsWith(".class"))
c = c.substring(0, c.length() - 6);
}
return c;
}
String cleanDesc(Block b) {
String t = b.description;
// if (!(b instanceof IIPBlock)) {
if (t == null || t.equals(""))
t = "_comp_";
t = t.replace('"', '\u0007');
Pattern p;
Matcher ma;
if (fbpMode) {
t = t.replace('_', '\u0007');
p = Pattern.compile("\\p{Punct}"); // punctuation chars
ma = p.matcher(t);
String u = "";
int i = 0;
while (ma.find(i)) {
String s = "\\" + ma.group();
u += t.substring(i, ma.start()) + s;
i = ma.end();
}
u += t.substring(i);
t = u;
}
p = Pattern.compile("\\s"); // whitespace chars
ma = p.matcher(t);
t = ma.replaceAll("_");
t = t.replace('\u0007', '_');
return makeUniqueDesc(t); // and make it unique
}
boolean getPortNames(Arrow arrow) {
Block from = diag.blocks.get(new Integer(arrow.fromId));
Arrow a2 = arrow.findArrowEndingAtBlock();
Block to = diag.blocks.get(new Integer(a2.toId));
String z;
if (from instanceof ProcessBlock) {
upPort = arrow.upStreamPort;
while (true) {
if (upPort != null && !(upPort.equals(""))) {
z = validatePortName(upPort);
if (z != null) {
upPort = z;
break;
}
if (MyOptionPane.NO_OPTION == MyOptionPane.showConfirmDialog(
driver.frame, "Invalid port name: " + upPort,
"Invalid output port name - try again?",
MyOptionPane.YES_NO_OPTION)) {
// ok = false;
upPort = "????";
break;
}
}
upPort = (String) MyOptionPane.showInputDialog(driver.frame,
"Output port from " + "\"" + from.description + "\"",
"Please enter port name");
if (upPort == null)
return false;
diag.changed = true;
}
arrow.upStreamPort = upPort;
}
dnPort = a2.downStreamPort;
while (true) {
if (dnPort != null && !(dnPort.equals(""))) {
z = validatePortName(dnPort);
if (z != null) {
dnPort = z;
break;
}
if (MyOptionPane.NO_OPTION == MyOptionPane.showConfirmDialog(
driver.frame, "Invalid port name: " + dnPort,
"Invalid input port name - try again?",
MyOptionPane.YES_NO_OPTION)) {
// ok = false;
dnPort = "????";
break;
}
}
dnPort = (String) MyOptionPane.showInputDialog(driver.frame,
"Input port to " + "\"" + to.description + "\"",
"Please enter port name");
if (dnPort == null)
return false;
diag.changed = true;
}
a2.downStreamPort = dnPort;
return true;
}
String validatePortName(String s) {
if (s == null || s.equals("") || s.equals("????"))
return null;
Pattern p = Pattern.compile("[a-zA-Z][\\d\\-\\_\\.\\[\\]a-zA-Z]*"); // Allow
// hyphen
// (for
// Humberto),
// period
// (for
// Tom),
// underscore
// and square brackets
Matcher ma = p.matcher(s);
if (!ma.matches())
return null;
else
return s;
}
}