/*
* ConnectionSpecXMLGenerator
*
*
* Copyright (c) 2003 Kansas State University, Laboratory for the Specification,
* Analysis, and Transformation of Software
*
* This software is licensed under the SAnToS Laboratory Open Academic License. You
* should have received a copy of the license with the distribution. A copy can be
* found at:
* http://www.cis.ksu.edu/santos/license.html
* or you can contact the lab at:
* SAnToS Laboratory
* 234 Nichols Hall
* Manhattan, KS 66506, USA
*/
package edu.ksu.cis.cadena.xmlgen;
import edu.ksu.cis.cadena.frontend.ComponentLibrary;
import edu.ksu.cis.cadena.frontend.cad.analysis.DefaultASTVisitor;
import edu.ksu.cis.cadena.frontend.cad.parser.BasicEventConnection;
import edu.ksu.cis.cadena.frontend.cad.parser.Connection;
import edu.ksu.cis.cadena.frontend.cad.parser.CorrelatedEventConnection;
import edu.ksu.cis.cadena.frontend.cad.parser.DataConnection;
import edu.ksu.cis.cadena.frontend.cad.parser.InstanceDecl;
import edu.ksu.cis.cadena.frontend.cad.parser.Scenario;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/**
* <p>
* This class generates the KSU Event Service connection configuration XML file,
* only BasicEventConnection and CorrelatedEventConnection are considered.
* DataConnection is not used in this class
* <p>
* @version 1.0.3
* @author Sue Li
*
*/
public class ConnectionSpecXMLGenerator extends DefaultASTVisitor {
/** maps instance name to its ID*/
private Map instanceToIDs;
/** maps instance name to another map (which maps port name to eventID)*/
private Map instancePorts;
/** the next eventID number*/
private int eventID;
/** the root of Document Of */
private Document document;
/** the output XML file*/
private File theFile;
/** the output file writer*/
private PrintWriter out;
/** the root element*/
private Element rootElement;
/**
* class constructor initializes variavles
*
* @param directory the directory of output file
*/
public ConnectionSpecXMLGenerator(String directory) {
assert directory != null;
try {
instancePorts = new HashMap(); //instance names to maps which keep maps the port names to event IDs
instanceToIDs = new HashMap(); //instance names to IDs
eventID = 1;
theFile = new File(directory+"connection.xml");
out = new PrintWriter(new BufferedWriter(new FileWriter(theFile)));
} catch (Exception e) {
System.out.println(e);
}
}
/**
* gets the instancePorts map
* @return a map
*/
public Map getInstancePortsMap(){
return instancePorts;
}
/**
* Constructor ConnectionSpecXMLGenerator
*/
public ConnectionSpecXMLGenerator() {
try {
instancePorts = new HashMap(); //instance names to maps which keep maps the port names to event IDs
instanceToIDs = new HashMap(); //instance names to IDs
eventID = 1;
} catch (Exception e) {
System.out.println(e);
}
}
/**
* sets the XML file name and creates a new file for the output
* @param name the output file name
* @throws IOException
*/
public void setFileName(String name) {
assert name != null;
try {
theFile = new File(name);
out = new PrintWriter(new BufferedWriter(new FileWriter(theFile)));
} catch (Exception e) {
System.out.println(e);
}
}
/**
* visits the root of Scenario, generates the root of output file,
* assign a unique id to each componet instance,
* starts to visit connections of each instance,
* tanslates the xml information into file
*
* @see buildDom()
* @see generateXML(PrintWriter)
* @see visit(DataConnection, Object)
* @see visit(BasicEventConnection, Object)
* @see visit(CorrelatedEventConnection, Object)
*
* @param node the root of scenario
* @param input not used here
* @return null
*/
public Object visit(Scenario node, Object input) {
assert node != null;
buildDOM();
int componentID = 1;
for (Iterator iterator = node.getInstanceList().iterator();
iterator.hasNext();) {
InstanceDecl instance = (InstanceDecl) iterator.next();
/*
* assign a unique componentID to each instance including EventChannel
* and put the id to instanceToIDs map
*/
int last = instance.getBuildingBlock().trim().lastIndexOf(":") + 1;
String instanceName =
instance.getBuildingBlock().trim().substring(last);
instanceToIDs.put(instance.getName(), new Integer(componentID));
Map portNames = new HashMap();
instancePorts.put(instance.getName(), portNames);
componentID++;
}
assert componentID == (node.getInstanceList().size() + 1);
for (Iterator iterator = node.getInstanceList().iterator();
iterator.hasNext();) {
InstanceDecl instance = (InstanceDecl) iterator.next();
int last = instance.getBuildingBlock().trim().lastIndexOf(":") + 1;
String instanceName =
instance.getBuildingBlock().trim().substring(last);
for (Iterator it = instance.getConnections().iterator();
it.hasNext();) {
Connection c = (Connection) it.next();
c.apply(this, instance);
}
}
generateXML(out);
out.close();
return null;
}
/**
* visits DataConnection, not really used here
*
* @param node the DataConnection
* @param input not used here
* @return null
*/
public Object visit(DataConnection node, Object input) {
assert node != null;
assert input instanceof InstanceDecl;
return null;
}
/**
* visits BasicEventConnection,
* gets the name of service,
* if the from instance name of this connecion equals to the name of the owner of this connection,
* builds the connection
*
* @see buildConnection(int, String, int, String, String, int, String,String, String)
*
* @param node the BasicEventConnection
* @param input the owner of this connection
* @return null
*/
public Object visit(BasicEventConnection node, Object input) {
assert node != null;
assert input instanceof InstanceDecl;
String instanceName = ((InstanceDecl) input).getName();
String fromName = node.getFromInstance().getName();
String fromLocation = node.getFromInstance().getLocation().toString();
String toName = node.getToInstance().getName();
String toLocation = node.getToInstance().getLocation().toString();
String service = "KSUES";
if (node.hasThrough()) {
String tempService = node.getThrough();
if (!tempService.trim().equals("")) {
service = tempService;
}
}
if (fromName.equals(instanceName)) {
int producerID = ((Integer) instanceToIDs.get(fromName)).intValue();
int consumerID = ((Integer) instanceToIDs.get(toName)).intValue();
String eventName = node.getType();
eventName = getPrefix(eventName);
String fromPort = node.getFromPort();
String toPort = node.getToPort();
Map portMap = (Map) instancePorts.get(fromName);
if (!portMap.containsKey(fromPort)) {
portMap.put(fromPort,
new PortEntryInformation(eventID, service.equals("CCM"),
service.equals("KSUES")));
buildConnection(producerID, service, 1, eventName, fromPort,
eventID, "0", fromName, fromLocation);
buildConnection(consumerID, service, 2, eventName, toPort,
eventID, "0", toName, toLocation);
eventID++;
} else {
PortEntryInformation entry =
((PortEntryInformation) portMap.get(fromPort));
int id = entry.getEventID();
boolean noCurrentServiceEntry =
(service.equals("CCM") && !entry.hasCCM())
|| (service.equals("KSUES") && !entry.hasKSUES());
if (noCurrentServiceEntry) {
buildConnection(producerID, service, 1, eventName,
fromPort, id, "0", fromName, fromLocation);
}
buildConnection(consumerID, service, 2, eventName, toPort, id,
"0", toName, toLocation);
}
}
return null;
}
/**
* visits CorrelatedEventConnection,
* gets the name of service,
* if this connecion is in a supplier instance, assign an eventID to this connection, builds the supplier part for this connection
* @consumer part connection in XML file
*
* @see buildConnection(int, String, int, String, String, int, String,String, String)
*
* @param node the CorrelatedEventConnection
* @param input the owner of this connection
* @return null
*/
public Object visit(CorrelatedEventConnection node, Object input) {
assert node != null;
assert input instanceof InstanceDecl;
String service = "KSUES";
if (node.hasThrough()) {
String tempService = node.getThrough();
if (!tempService.trim().equals("")) {
service = tempService;
}
}
/* builds correlated event consumer*/
if (!node.isIncoming()) {
String eventType = node.getType();
eventType = getPrefix(eventType);
String consumerName = ((InstanceDecl) input).getName();
String consumerLocation =
((InstanceDecl) input).getLocationString();
String consumerPort = node.getPort();
int consumerId =
((Integer) instanceToIDs.get(consumerName)).intValue();
buildConnection(consumerId, service, 2, eventType, consumerPort,
eventID, "0", consumerName, consumerLocation);
eventID++;
} else { //builds correlated event producer
String eventTypePro = node.getType();
eventTypePro = getPrefix(eventTypePro);
String producerName = node.getInstance().getName();
String producerLocation = node.getInstance().getLocationString();
String producerPort = node.getPort();
int producerId =
((Integer) instanceToIDs.get(producerName)).intValue();
Map portMap = (Map) instancePorts.get(producerName);
if (!portMap.containsKey(producerPort)) {
portMap.put(producerPort,
new PortEntryInformation(eventID, service.equals("CCM"),
service.equals("KSUES")));
buildConnection(producerId, service, 1, eventTypePro,
producerPort, eventID, "0", producerName, producerLocation);
eventID++;
} else {
PortEntryInformation entry =
(PortEntryInformation) (portMap.get(producerPort));
int id = entry.getEventID();
boolean noCurrentServiceEntry =
(service.equals("CCM") && !entry.hasCCM())
|| (service.equals("KSUES") && !entry.hasKSUES());
if (noCurrentServiceEntry) {
buildConnection(producerId, service, 1, eventTypePro,
producerPort, id, "0", producerName, producerLocation);
}
}
}
return null;
}
/**
* builds the connection in XML file
*
* @param id component instance id
* @param service the tool name that provides the connection service KSUES or other services
* @param type the role of the event 0 for supplier and 1 for consumer
* @param eventName the event type name
* @param portName the port name
* @param eventID the event ID
* @param syn synchronziation type 0 for no and 1 for yes
* @param name component instance name
* @param location the name of the board where the instance is located on
*/
private void buildConnection(int id, String service, int type,
String eventName, String portName, int eventID, String syn,
String name, String location) {
Element connection =
(Element) document.createElement("connection_spec");
rootElement.appendChild(connection);
Element comname = (Element) document.createElement("component_name");
comname.appendChild(document.createTextNode(name.trim()));
connection.appendChild(comname);
Element comID = (Element) document.createElement("component_id");
comID.appendChild(document.createTextNode(String.valueOf(id)));
connection.appendChild(comID);
Element serEle = (Element) document.createElement("service");
serEle.appendChild(document.createTextNode(service));
connection.appendChild(serEle);
Element role = (Element) document.createElement("role");
role.appendChild(document.createTextNode(String.valueOf(type)));
connection.appendChild(role);
Element eventname = (Element) document.createElement("event_name");
eventname.appendChild(document.createTextNode(eventName));
connection.appendChild(eventname);
Element eventport = (Element) document.createElement("port_name");
eventport.appendChild(document.createTextNode(portName));
connection.appendChild(eventport);
Element eventid = (Element) document.createElement("event_id");
eventid.appendChild(document.createTextNode(String.valueOf(eventID)));
connection.appendChild(eventid);
Element sync = (Element) document.createElement("sync_id");
sync.appendChild(document.createTextNode(syn));
connection.appendChild(sync);
Element loc = (Element) document.createElement("location");
loc.appendChild(document.createTextNode(location));
connection.appendChild(loc);
}
/**
* creates the root of the XML file
* @throws ParserConfigurationException
*/
public void buildDOM() {
try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument(); // Create from whole cloth
} catch (ParserConfigurationException pce) {
//Parser with specified options can't be built
pce.printStackTrace();
}
rootElement = (Element) document.createElement("configuration");
document.appendChild(rootElement);
}
/**
* translates the document into XML file
*
* @throws TransformerConfigurationException
* @throws TransformerException
*
* @param out the output file
*
*/
public void generateXML(PrintWriter out) {
try {
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //set indent true
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(out);
transformer.transform(source, result);
} catch (TransformerConfigurationException tce) {
System.out.println("* Transformer Factory error");
System.out.println("* " + tce.getMessage());
// Use the contained exception, if any
Throwable x = tce;
if (tce.getException() != null) {
x = tce.getException();
}
x.printStackTrace();
} catch (TransformerException te) {
System.out.println("* Transformation error");
System.out.println(" " + te.getMessage());
//Use the contained exception, if any
Throwable x = te;
if (te.getException() != null) {
x = te.getException();
}
x.printStackTrace();
}
}
/**
* replaces ":" and "::" by "." and removes any characters before the first letter
* @param name the string need to be modified
* @return return a string whose ":" and "::" replaced by "."
*/
private String getPrefix(String name) {
assert name != null;
int beginIndex = 0;
if (name.startsWith(":")) {
beginIndex = 2;
}
String modalName =
name.substring(beginIndex, name.indexOf(":", beginIndex));
ComponentLibrary comLib = ComponentLibrary.getComponentLibrary();
String prefix = comLib.getPrefix(modalName);
String postfix =
edu.ksu.cis.cadena.frontend.cad.parser.ImportLib
.convertCorbaNameToJava(name);
if (!prefix.trim().equals("")) {
return prefix + postfix;
} else {
return postfix.substring(1);
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1