/** * SAMOA - PROTOCOL FRAMEWORK * Copyright (C) 2005 Olivier Rütti (EPFL) (olivier.rutti@a3.epfl.ch) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package seqSamoa.GUIcomposer.GraphicalObjects; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.swing.JOptionPane; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import seqSamoa.GUIcomposer.XMLProtocolAndServiceDatabase; import seqSamoa.GUIcomposer.XMLProtocolAndServiceDatabase.ParameterXML; import seqSamoa.GUIcomposer.XMLProtocolAndServiceDatabase.ProtocolXML; public class StackManager { private ProtocolsManager protocolsManager; private LinksManager linksManager; private ProtocolPanel draggedProtocolPanel; private ServicePanel selectedServicePanel; private int prevMousePositionX; private int prevMousePositionY; // indicates if the is trying to add a new link private boolean userIsDrawingLink; private int linkX; private int linkY; protected XMLProtocolAndServiceDatabase readerXML; public StackManager(XMLProtocolAndServiceDatabase readerXML) { this.readerXML = readerXML; protocolsManager = new ProtocolsManager(); linksManager = new LinksManager(); } /** * draw the stack * * @param g * @param w * the width of canvas * @param h * the height of the cancas */ public void drawStack(Graphics g, int w, int h) { // draw the protocols of the stack protocolsManager.drawProtocols(g, w, h); // draw the links of the stack linksManager.drawLinks(g); Graphics2D g2d = (Graphics2D) g; g2d.setStroke(new BasicStroke(2)); // if the user is attempting to add a new link if (userIsDrawingLink) { g2d.setColor(Color.black); if (protocolsManager .servicePanelIsAProvidedService(selectedServicePanel)) g2d.drawLine(selectedServicePanel.pos.x, selectedServicePanel.pos.y - selectedServicePanel.height, linkX, linkY); else g2d.drawLine(selectedServicePanel.pos.x, selectedServicePanel.pos.y, linkX, linkY); } } public void addLink(Link link) { // check if the new link is valid if (linksManager.linkIsValid(link)) linksManager.addLink(link); } public void createProtocolPanel(ProtocolXML protXML, String name, HashMap<ParameterXML, String> protocolParametersValues) { protocolsManager.addProtocolPanel(new ProtocolPanel(protXML, name, protocolParametersValues)); } public boolean isNameAlreadyUsed(String name) { List<ProtocolPanel> protocolsList = protocolsManager.allProtocols; for (int i = 0; i < protocolsList.size(); i++) { ProtocolPanel pPanel = (ProtocolPanel) protocolsList.get(i); if (pPanel.getName().equals(name)) return true; } return false; } /** * get the parameters of the selected protocol * * @return a list of elements representing the parameters of the selected * protocol */ public HashMap<ParameterXML, String> getSelectedProtocolParameters() { if (protocolsManager.selectedProtocol != null) { return protocolsManager.selectedProtocol.parameters; } return null; } /** * this method is called when the mouse is pressed * * @param x * the x coordinate of the mouse * @param y * the y coordinate of the mouse */ public void mousePressed(int x, int y) { prevMousePositionX = x; prevMousePositionY = y; if (protocolsManager.selectedProtocol != null) protocolsManager.selectedProtocol.color = Color.white; // check if the user is not clicking on a link if (linksManager.linkContainingPoint(x, y) == null) { // check if the user is not clicking on a ServicePanel selectedServicePanel = protocolsManager .servicePanelContainingPoint(x, y); if (selectedServicePanel == null) { // check if the user is not clicking on a ProtocolPanel protocolsManager.protocolPanelContainingPoint(x, y); if (protocolsManager.selectedProtocol != null) { draggedProtocolPanel = protocolsManager.selectedProtocol; // prevMousePositionX = x; // prevMousePositionY = y; } else { draggedProtocolPanel = null; } } else { protocolsManager.selectProtocol(null); draggedProtocolPanel = null; } } else { protocolsManager.selectProtocol(null); draggedProtocolPanel = null; } } /** * this method is called when the mouse is dragged * * @param x * the x coordinate of the mouse * @param y * the y coordinate of the mouse * @param width * width of the canvas * @param height * height of the canvas */ public void mouseDragged(int x, int y, int width, int height) { if (linksManager.selectedLink != null) { // the user is dragging a ProtocolPanel int dx = x - prevMousePositionX; int dy = y - prevMousePositionY; linksManager.selectedLink.moveSelectedPart(dx, dy); prevMousePositionX = x; prevMousePositionY = y; } else if (selectedServicePanel != null) { // the user is trying to draw a link userIsDrawingLink = true; linkX = x; linkY = y; } else if (draggedProtocolPanel != null) { // the user is dragging a ProtocolPanel int dx = x - prevMousePositionX; int dy = y - prevMousePositionY; if (((draggedProtocolPanel.pos.x < 2) && (dx < 0)) || ((draggedProtocolPanel.pos.x > width - draggedProtocolPanel.width) && (dx > 0)) || (x < 10) || (x > width)) dx = 0; if (((draggedProtocolPanel.pos.y < 0) && (dy < 0)) || ((draggedProtocolPanel.pos.y > height - 5) && (dy > 0)) || (y < 12) || (y > height)) dy = 0; draggedProtocolPanel.moveBy(dx, dy); prevMousePositionX = x; prevMousePositionY = y; } } /** * this method is called when the button of the mouse is released * * @param x * the x coordinate of the mouse * @param y * the y coordinate of the mouse */ public void mouseReleased(int x, int y) { userIsDrawingLink = false; if (selectedServicePanel != null) { ServicePanel selectedServicePanel2 = protocolsManager .servicePanelContainingPoint(x, y); if (selectedServicePanel2 != null) { // check if the two servicePanels represents the same service // type if (selectedServicePanel.serviceXML.className.equals( selectedServicePanel2.serviceXML.className)) { ProtocolPanel protocolPanel1 = protocolsManager .getProtocolPanelContainingServicePanel(selectedServicePanel); ProtocolPanel protocolPanel2 = protocolsManager .getProtocolPanelContainingServicePanel(selectedServicePanel2); if (protocolPanel1 .servicePanelIsAProvidedService(selectedServicePanel) && !protocolPanel2 .servicePanelIsAProvidedService(selectedServicePanel2)) { addLink(new Link(protocolPanel1, protocolPanel2, selectedServicePanel.serviceXML.className)); } else if (protocolPanel2 .servicePanelIsAProvidedService(selectedServicePanel2) && !protocolPanel1 .servicePanelIsAProvidedService(selectedServicePanel)) { addLink(new Link(protocolPanel2, protocolPanel1, selectedServicePanel.serviceXML.className)); } } } else { if (y < 20) if (protocolsManager .getProtocolPanelContainingServicePanel( selectedServicePanel) .servicePanelIsAProvidedService( selectedServicePanel)) linksManager .addLink(new FinalLink( protocolsManager .getProtocolPanelContainingServicePanel(selectedServicePanel), selectedServicePanel.serviceXML.className)); } } } /** * this method is called when the mouse is moving * * @param x * the x coordinate of the mouse * @param y * the y coordinate of the mouse */ public void mouseMoved(int x, int y) { protocolsManager.servicePanelContainingPoint(x, y); } /*************************************************************************** * saves the constructed schema in the file "fileName" * * @param fileName * the name of the XML file in which the schema will be saved */ @SuppressWarnings("unchecked") public void saveSchema(String fileName) { Element schema = new Element("stack"); // Construct all services Element services = new Element("Services"); ArrayList<String> tmpServices = new ArrayList<String>(); ArrayList<FinalLink> allLinks = linksManager.linksList; for (int i = 0; i < allLinks.size(); i++) { FinalLink link = allLinks.get(i); String serviceName = link.providingProtocol.getName(); if (!tmpServices.contains(serviceName)){ Element service = link.getServiceElement(); services.addContent(service); tmpServices.add(serviceName); } else if (!(link instanceof Link)) { List servicesList = services.getChildren("Service"); for (int j = 0; j < servicesList.size(); j++) { Element service = (Element) servicesList.get(j); if (serviceName.equals(service.getChild("Name").getText())) service.getChild("ServiceFinal").setText("true"); } } } // Construct all protocols Element protocols = new Element("Protocols"); ArrayList<ProtocolPanel> allProtocols = protocolsManager.allProtocols; for (int i = 0; i < allProtocols.size(); i++) { ProtocolPanel pprot = (ProtocolPanel) allProtocols.get(i); Element protocol = pprot.getProtocolElement(); Element providedServices = protocol.getChild("ProvidedServices"); Element requiredServices = protocol.getChild("RequiredServices"); // Set the service requirements and "providements" for (int j = 0; j < allLinks.size(); j++) { FinalLink link = (FinalLink) allLinks.get(j); String serviceClassName = link.providedService.serviceXML.className; String serviceName = link.providingProtocol.getName(); // Provided Services if (link.providingProtocol.getName().equals(pprot.getName())) { Iterator itProvided = providedServices.getChildren("ProvidedService").iterator(); boolean toBeContinued = true; while (itProvided.hasNext() && toBeContinued) { Element serviceProvided = (Element) itProvided.next(); if (serviceProvided.getChildText("ClassName").equals(serviceClassName) && serviceProvided.getChildText("Name").equals("null")){ serviceProvided.getChild("Name").setText(serviceName); toBeContinued = false; } } } // Required Services if (link instanceof Link){ Link llink = (Link) link; if (llink.requiringProtocol.getName().equals(pprot.getName())) { Iterator itRequired = requiredServices.getChildren("RequiredService").iterator(); boolean toBeContinued = true; while (itRequired.hasNext() && toBeContinued) { Element serviceRequired = (Element) itRequired.next(); if (serviceRequired.getChildText("ClassName").equals(serviceClassName) && serviceRequired.getChildText("Name").equals("null")){ serviceRequired.getChild("Name").setText(serviceName); toBeContinued = false; } } } } } protocols.addContent(protocol); // Add Service that has no link Iterator itProvided = providedServices.getChildren("ProvidedService").iterator(); int nbUnNamed = 0; while (itProvided.hasNext()) { Element protServiceProvided = (Element) itProvided.next(); if (protServiceProvided.getChildText("Name").equals("null")) { nbUnNamed++; Element service = new Element("Service"); Element serviceClass = new Element("Class"); String scl = protServiceProvided.getChildText("ClassName"); Element serviceClassName = new Element("Name"); serviceClassName.setText(scl); Element servicePackageName = new Element("Package"); servicePackageName.setText(readerXML.getService(scl).packageName); serviceClass.addContent(serviceClassName); serviceClass.addContent(servicePackageName); Element serviceName = new Element("Name"); serviceName.setText(pprot.getName()+"UnNamed"+nbUnNamed); Element serviceFinal = new Element("ServiceFinal"); serviceFinal.setText("false"); Element serviceProvided = new Element("ServiceProvided"); serviceProvided.setText("true"); service.addContent(serviceClass); service.addContent(serviceName); service.addContent(serviceFinal); service.addContent(serviceProvided); services.addContent(service); protServiceProvided.getChild("Name").setText(pprot.getName()+"UnNamed"+nbUnNamed); } } Iterator itRequired = requiredServices.getChildren("RequiredService").iterator(); while (itRequired.hasNext()) { Element protServiceRequired = (Element) itRequired.next(); if (protServiceRequired.getChildText("Name").equals("null") && (!protServiceRequired.getChildText("ClassName").equals("Network"))) { nbUnNamed++; Element service = new Element("Service"); Element serviceClass = new Element("Class"); String scl = protServiceRequired.getChildText("ClassName"); Element serviceClassName = new Element("Name"); serviceClassName.setText(scl); Element servicePackageName = new Element("Package"); servicePackageName.setText(readerXML.getService(scl).packageName); serviceClass.addContent(serviceClassName); serviceClass.addContent(servicePackageName); Element serviceName = new Element("Name"); serviceName.setText(pprot.getName()+"UnNamed"+nbUnNamed); Element serviceFinal = new Element("ServiceFinal"); serviceFinal.setText("false"); Element serviceProvided = new Element("ServiceProvided"); serviceProvided.setText("false"); service.addContent(serviceClass); service.addContent(serviceName); service.addContent(serviceFinal); service.addContent(serviceProvided); services.addContent(service); protServiceRequired.getChild("Name").setText(pprot.getName()+"UnNamed"+nbUnNamed); } } } schema.addContent(services); schema.addContent(protocols); Document document = new Document(schema); try { XMLOutputter output = new XMLOutputter(Format.getPrettyFormat()); output.output(document, new FileOutputStream(fileName)); } catch (java.io.IOException e) { e.printStackTrace(); throw new RuntimeException("Exception upon file saving: "+e.getMessage()); } } /** * opens the saved schema in the file fileName * * @param fileName * the name of the XML file containing the saved schema */ @SuppressWarnings("unchecked") public void openSchema(String fileName) { try { SAXBuilder sxb = new SAXBuilder(); Document document = sxb.build(new File(fileName)); Element schema_root = (Element) document.getRootElement().clone(); Element protocolsElement = schema_root.getChild("Protocols"); Element servicesElement = schema_root.getChild("Services"); protocolsManager.allProtocols = new ArrayList<ProtocolPanel>(); linksManager.linksList = new ArrayList<FinalLink>(); // recover the list of all the protocols in the stack Iterator itProt = protocolsElement.getChildren("Protocol").iterator(); while (itProt.hasNext()) { Element protocol = (Element) itProt.next(); int posX = Integer.parseInt(protocol.getChild("Position").getChildText("PositionX")); int posY = Integer.parseInt(protocol.getChild("Position").getChildText("PositionY")); String className = protocol.getChild("Class").getChildText("Name"); String packageName = protocol.getChild("Class").getChildText("Package"); String name = protocol.getChildText("Name"); ProtocolXML protXML = readerXML.getProtocol(packageName, className); HashMap<ParameterXML, String> protParameters = new HashMap<ParameterXML, String>(); Iterator itParams = protocol.getChild("Parameters").getChildren("Parameter").iterator(); while (itParams.hasNext()){ Element parameter = (Element) itParams.next(); String paramName = parameter.getChildText("Name"); String paramValue = parameter.getChildText("Value"); protParameters.put(readerXML.getParameter(paramName), paramValue); } // Construct the Panel for the protocol ProtocolPanel protocolPanel = new ProtocolPanel(protXML, name, protParameters, posX, posY); protocolsManager.addProtocolPanel(protocolPanel); } // recover the list of links in the stack itProt = protocolsElement.getChildren("Protocol").iterator(); while (itProt.hasNext()) { Element protocol = (Element) itProt.next(); String protocolName = protocol.getChildText("Name"); ProtocolPanel pRequirer = protocolsManager.getProtocolPanelByProtocolName(protocolName); Iterator itRequired = protocol.getChild("RequiredServices").getChildren("RequiredService").iterator(); while (itRequired.hasNext()){ Element required = (Element) itRequired.next(); String requiredType = required.getChildText("ClassName"); String requiredName = required.getChildText("Name"); ProtocolPanel pProvider = protocolsManager.getProtocolPanelByProtocolName(requiredName); if (pProvider != null) linksManager.addLink(new Link(pProvider, pRequirer, requiredType)); } } Iterator itServices = servicesElement.getChildren("Service").iterator(); while (itServices.hasNext()) { Element service = (Element) itServices.next(); boolean isFinal = Boolean.parseBoolean(service.getChildText("ServiceFinal")); if (isFinal){ String serviceName = service.getChildText("Name"); String serviceType = service.getChild("Class").getChildText("Name"); ProtocolPanel pProvider = protocolsManager.getProtocolPanelByProtocolName(serviceName); linksManager.addLink(new FinalLink(pProvider, serviceType)); } } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Exception upon file opening: "+e.getMessage()); } } /** * delete the selected object from the stack */ public void deleteSelectedObject() { if (linksManager.selectedLink != null) linksManager.removeLink(linksManager.selectedLink); if (protocolsManager.selectedProtocol != null){ for (int i = 0; i < linksManager.linksList.size(); i++){ FinalLink fl = (FinalLink) linksManager.linksList.get(i); if (fl.providingProtocol.getName().equals(protocolsManager.selectedProtocol.getName())){ linksManager.removeLink(fl); i--; } else if (fl instanceof Link){ Link l = (Link) fl; if (l.requiringProtocol.getName().equals(protocolsManager.selectedProtocol.getName())){ linksManager.removeLink(l); i--; } } } protocolsManager.removeProtocol(protocolsManager.selectedProtocol); } } public void modifySelectedProtocolParameters(HashMap<ParameterXML, String> parameters) { if (checkParametersValidity(parameters)) protocolsManager.selectedProtocol.parameters = parameters; } /** * check the validity of un entered parameter * * @param parametersNames * the name of the parameter * @param parametersValues * the value of the parameter * @return true if the entered parameter is valid and false if */ private boolean checkParametersValidity(HashMap<ParameterXML, String> parameters) { String parameterName, parameterValue; Iterator<ParameterXML> it = parameters.keySet().iterator(); while (it.hasNext()) { parameterName = it.next().name; parameterValue = (String) parameters.get(parameterName); if (parameterValue.equals("") || parameterValue.equals(" ")) { JOptionPane.showMessageDialog(null, "you have to provide a value for the parameter : " + parameterName, "error", JOptionPane.ERROR_MESSAGE); return false; } if (parameterName.equals("name")) { if (!parameterValue.equals(protocolsManager .selectedProtocol.getName())) { for (int i = 0; i < protocolsManager.allProtocols.size(); i++) { if (protocolsManager.allProtocols.get(i).equals(parameterValue)) { JOptionPane.showMessageDialog(null, "the entered name is already attributed", "error", JOptionPane.ERROR_MESSAGE); } } } } if (readerXML.getParameter(parameterName).type.equals("int")) { try { Integer.parseInt(parameterValue); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "the value of the parameter " + parameterName + " must be an integer", "error", JOptionPane.ERROR_MESSAGE); return false; } } if (readerXML.getParameter(parameterName).type.equals("long")) { try { Long.parseLong(parameterValue); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "the value of the parameter " + parameterName + " must be an integer", "error", JOptionPane.ERROR_MESSAGE); return false; } } if (readerXML.getParameter(parameterName).type.equals("boolean")) { if (parameterValue.toLowerCase().equalsIgnoreCase("true") || parameterValue.toLowerCase().equalsIgnoreCase( "false")) { JOptionPane.showMessageDialog(null, "this paramter is a boolean(true or false)", "error", JOptionPane.ERROR_MESSAGE); return false; } } } // return true; } public void mouseClicked(int x, int y, int numberOfClicks) { if (numberOfClicks == 2) if (linksManager.selectedLink != null) linksManager.selectedLink.mouseDoubleClicked(x, y); } /** * Return all protocols in the stack */ public ArrayList<ProtocolPanel> getAllProtocols(){ return protocolsManager.allProtocols; } }