Skip to content
Snippets Groups Projects
TMLSDInstance.java 12.81 KiB
/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille, Andrea Enrici
 * 
 * ludovic.apvrille AT telecom-paristech.fr
 * andrea.enrici AT telecom-paristech.fr
 * 
 * This software is a computer program whose purpose is to allow the
 * edition of TURTLE analysis, design and deployment diagrams, to
 * allow the generation of RT-LOTOS or Java code from this diagram,
 * and at last to allow the analysis of formal validation traces
 * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP
 * from INRIA Rhone-Alpes.
 * 
 * This software is governed by the CeCILL  license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 * 
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 * 
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
 */




package ui.tmlsd;

import myutil.GraphicLib;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import ui.*;
import ui.util.IconManager;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;

//Abstract class, getType() and editOndoubleClick( JFrame ) are abstract
/**
 * Class TMLSDInstance
 * Instance of a TML sequence diagram
 * Creation: 17/02/2004
 * @version 1.1 10/06/2014
 * @author Ludovic APVRILLE, Andrea ENRICI
 */
public abstract class TMLSDInstance extends TGCWithInternalComponent implements SwallowTGComponent {

	//protected int lineLength = 5;
	//protected int textX, textY;
	protected int spacePt = 10;
	protected int wText = 10, hText = 15;
	protected int increaseSlice = 250;
	protected boolean isActor;
	protected static int heightActor = 30;
	protected static int widthActor = 16;
	protected LinkedList<TAttribute> myAttributes;
	protected String mappedUnit = "";	//The arch unit where the instance is mapped to


	public TMLSDInstance(int _x, int _y, int _minX, int _maxX, int _minY, int _maxY, boolean _pos, TGComponent _father, TDiagramPanel _tdp)  {
		super(_x, _y, _minX, _maxX, _minY, _maxY, _pos, _father, _tdp);

		width = 10;
		height = 500;
		//textX = 0;
		//textY = 2;
		minWidth = 10;
		maxWidth = 10;
		minHeight = 250;
		maxHeight = 1500;
		makeTGConnectingPoints();
		//addTGConnectingPointsComment();
		nbInternalTGComponent = 0;
		moveable = true;
		editable = true;
		removable = true;
		userResizable = true;
		value = "Instance name";
		name = "instance";
		myAttributes = new LinkedList<TAttribute> ();
		myImageIcon = IconManager.imgic500;
	}

	public void internalDrawing(Graphics g) {
		if (!tdp.isScaled()) {
			wText  = g.getFontMetrics().stringWidth(name);
			hText = g.getFontMetrics().getHeight();
		}
		g.drawString(name, x - (wText / 2) + width/2, y - 3);
		g.drawLine(x - (wText / 2) + width/2, y-2, x + (wText / 2) + width/2, y-2);
		g.drawLine(x+(width/2), y, x+(width/2), y +height);

		if (isActor) {
			int xtmp = x + (width-widthActor) / 2;
			int ytmp = y-hText;
			// Head
			g.drawOval(xtmp+(widthActor/4)-1, ytmp-heightActor, 2+widthActor/2, 2+widthActor/2);
			//Body
			g.drawLine(xtmp+widthActor/2, ytmp-heightActor/3, xtmp+widthActor/2, ytmp-(2*heightActor)/3);
			//Arms
			g.drawLine(xtmp, ytmp-(heightActor/2) - 2, xtmp+widthActor, ytmp-(heightActor/2) - 2);
			//Left leg
			g.drawLine(xtmp+widthActor, ytmp, xtmp+widthActor/2, ytmp-heightActor/3);
			//right leg
			g.drawLine(xtmp, ytmp, xtmp+widthActor/2, ytmp-heightActor/3);
		}
	}

	public TGComponent isOnOnlyMe(int _x, int _y) {
		if (GraphicLib.isInRectangle(_x, _y, x, y, width, height)) {
			return this;
		}

		if (GraphicLib.isInRectangle(_x, _y, x + (width/2) - (wText/2) , y-hText, wText, hText)) {
			return this;
		}

		if (isActor) {
			if (GraphicLib.isInRectangle(_x, _y, x + (width-widthActor) / 2, y-heightActor-hText, widthActor, heightActor)) {
				return this;
			}
		}
		return null;
	}

	public int getMyCurrentMinX() {
		return Math.min(x + (width/2) - (wText/2), x);

	}

	public int getMyCurrentMaxX() {
		return Math.max(x + (width/2) + (wText/2), x + width);
	}

	public int getMyCurrentMinY() {
		return Math.min(y-hText-heightActor, y);
	}

	public String getInstanceName() {
		return getName();
	}

	public abstract int getType();

	protected void makeTGConnectingPoints() {

		nbConnectingPoint = ( (height - (2 * spacePt) ) / spacePt ) + 1;
		connectingPoint = new TGConnectingPoint[ nbConnectingPoint ];

		int yh = spacePt;

		for(int i = 0; i < nbConnectingPoint; i++, yh += spacePt ) {
			connectingPoint[i] = new TGConnectingPointTMLSD(this, ( width/2), yh, true, true );
		}

	}

	public abstract boolean editOndoubleClick( JFrame frame );

	public boolean acceptSwallowedTGComponent(TGComponent tgc) {
        return (tgc instanceof TMLSDActionState);
    }

	public boolean addSwallowedTGComponent(TGComponent tgc, int x, int y) {
		if (!acceptSwallowedTGComponent(tgc)) {
			return false;
		}


		//
		// Choose its position
		int realY = Math.max(y, getY() + spacePt);
		realY = Math.min(realY, getY() + height + spacePt);
		int realX = tgc.getX();


		// Make it an internal component
		// It's one of my son
		tgc.setFather(this);
		tgc.setDrawingZone(true);



		if ((tgc instanceof TMLSDActionState)) {
			realX = getX()+(width/2);
			//tgc.setCdRectangle((width/2), (width/2), spacePt, height-spacePt-tgc.getHeight());
			tgc.setCd(realX, realY);
		}

		setCDRectangleOfSwallowed(tgc);


		//add it
		addInternalComponent(tgc, 0);

		return true;
	}

	public void removeSwallowedTGComponent(TGComponent tgc) {
		removeInternalComponent(tgc);
	}



	// previous in the sense of with y the closer and before
	public TGComponent getPreviousTGComponent(TGComponent tgcToAnalyse) {
		int close = Integer.MAX_VALUE;
		TGComponent tgc;
		TGComponent tgcfound = null;
		int diff;

		for(int i=0; i<nbInternalTGComponent; i++) {
			tgc = tgcomponent[i];
			if (tgc != tgcToAnalyse) {
				diff = tgcToAnalyse.getY() - tgc.getY();
				if ((diff > 0) && (diff < close)) {

					close = diff;
					tgcfound = tgc;


				}
			}
		}

		return tgcfound;
	}

	public TGComponent getTGComponentActionCloserTo(TGComponent tgc) {
		/* action : message send, message receive, other ? */
		/* timers ? */
		/* now: only message! */

		return ((TMLSDPanel)tdp).messageActionCloserTo(tgc, this);

	}

	public void addActionToPopupMenu(JPopupMenu componentMenu, ActionListener menuAL, int x, int y) {
		componentMenu.addSeparator();

		JMenuItem decrease = new JMenuItem("Decrease size");
		decrease.addActionListener(menuAL);
		componentMenu.add(decrease);
		decrease.setEnabled(canDecreaseSize());
		JMenuItem increase = new JMenuItem("Increase size");
		increase.addActionListener(menuAL);
		componentMenu.add(increase);
	}

	public boolean eventOnPopup(ActionEvent e) {
		if ((e.getActionCommand().compareTo("Decrease size")) == 0) {
			decreaseSize();
		} else {
			increaseSize();
		}
		return true;
	}

	public void updateMinMaxSize() {
		minHeight = 250;
		int i;

		for(i=0; i<connectingPoint.length ; i++) {
			if (!connectingPoint[i].isFree()) {
				minHeight = Math.max(minHeight, connectingPoint[i].getY() - y);
			}
		} 

		for(i=0; i<nbInternalTGComponent ; i++) {
			minHeight = Math.max(minHeight, tgcomponent[i].getY() + tgcomponent[i].getHeight()- y);
		}
	}

	public boolean canDecreaseSize() {
		if (height <= increaseSlice) {
			return false;
		}

		int newNbConnectingPoint = (((height-increaseSlice) - (2 * spacePt)) / spacePt) + 1;
		int i;

		for(i=newNbConnectingPoint; i<connectingPoint.length ; i++) {
			if (!connectingPoint[i].isFree()) {
				//
				return false;
			}
		} 

		//SwallowedComponents
		for(i=0; i<nbInternalTGComponent ; i++) {
			//
			if ((tgcomponent[i].getY() + tgcomponent[i].getHeight()) > (getY() + getHeight() - increaseSlice)) {
				//
				return false;
			}
		}

		return true;
	}

	public void decreaseSize() {
		//
		//Check whether it is possible or not (swallowed components and tgconnecting points used
		if (!canDecreaseSize()) {
			return;
		}
		// new nb of connectingPoints

		// If ok, do the modification
		height = height - increaseSlice;
		hasBeenResized();
	}

	public void increaseSize() {
		//
		height = height + increaseSlice;
		hasBeenResized();
	}

	public void hasBeenResized(){
		int i;

		TGConnectingPoint [] connectingPointTmp = connectingPoint;
		makeTGConnectingPoints();
		for(i=0; i<Math.min(connectingPointTmp.length, connectingPoint.length) ; i++) {
			connectingPoint[i] = connectingPointTmp[i];
		} 

		// Increase tdp if necessary?

		// Reposition each swallowed component
		for(i=0; i<nbInternalTGComponent ; i++) {
			setCDRectangleOfSwallowed(tgcomponent[i]);
		}
	}

	protected void setCDRectangleOfSwallowed(TGComponent tgc) {


		if ((tgc instanceof TMLSDActionState)) {
			tgc.setCdRectangle((width/2), (width/2), spacePt, height-spacePt-tgc.getHeight());
		}


	}

	protected String translateExtraParam() {
		StringBuffer sb = new StringBuffer( "<extraparam>\n" );
		sb.append( "<Mapping mappedOn=\"" );
		sb.append( "" + mappedUnit );
		sb.append( "\" />\n" );
		sb.append( "<Actor data=\"" );
		sb.append( ""+isActor );
		sb.append( "\" />\n" );
		for (TAttribute a: myAttributes) {
			sb.append( "<Attribute access=\"" );
			sb.append( a.getAccess() );
			sb.append( "\" id=\"" );
			sb.append( a.getId() );
			sb.append( "\" value=\"" );
			sb.append( a.getInitialValue() );
			sb.append( "\" type=\"" );
			sb.append( a.getType() );
			sb.append( "\" typeOther=\"" );
			sb.append( a.getTypeOther() );
			sb.append( "\" />\n" );
		}
		sb.append( "</extraparam>\n" );
		return new String(sb);
	}

	@Override
	public void loadExtraParam( NodeList nl, int decX, int decY, int decId ) throws MalformedModelingException{
		//
		try {
			NodeList nli;
			Node n1, n2;
			Element elt;
			int access, type;
			String typeOther;
			String id, valueAtt;

			for( int i = 0; i < nl.getLength(); i++ ) {
				n1 = nl.item(i);
				//
				if( n1.getNodeType() == Node.ELEMENT_NODE ) {
					nli = n1.getChildNodes();

					// Issue #17 copy-paste error on j index
					for( int j = 0; j < nli.getLength(); j++ ) {
						n2 = nli.item(j);
						//
						if( n2.getNodeType() == Node.ELEMENT_NODE ) {
							elt = (Element) n2;
							if( elt.getTagName().equals("Mapping") ) {
								mappedUnit = elt.getAttribute("mappedOn");
							}
							if( elt.getTagName().equals("Actor") ) {
								if( elt.getAttribute("data").compareTo("true") == 0 ) {
									isActor = true;
								}
							}
							//TraceManager.addDev( "I am analyzing " + elt.getTagName() );	
							if( elt.getTagName().equals("Attribute") )	{
								//TraceManager.addDev("Analyzing attribute");
								access = Integer.decode(elt.getAttribute("access")).intValue();
								type = Integer.decode(elt.getAttribute("type")).intValue();
								try {
									typeOther = elt.getAttribute("typeOther");
								}
								catch ( Exception e )	{
									typeOther = "";
								}
								id = elt.getAttribute("id");
								valueAtt = elt.getAttribute("value");
								if( valueAtt.equals("null") )	{
									valueAtt = "";
								}
								if( (TAttribute.isAValidId(id, false, false, false) ) && ( TAttribute.isAValidInitialValue(type, valueAtt)) )	{
									//TraceManager.addDev("Adding attribute " + id + " typeOther=" + typeOther);
									TAttribute ta = new TAttribute(access, id, valueAtt, type, typeOther);
									myAttributes.add (ta);
								}
							}
						}
					}
				}
			}
		}
		catch ( Exception e ) {
			throw new MalformedModelingException();
		}
	}

	public void setActor(boolean b) {
		isActor = b;
	}

	public int getNumberInternalComponents()	{
		return nbInternalTGComponent;
	}

	public TGComponent[] getInternalComponents()	{
		return tgcomponent;
	}

	public TGConnectingPoint[] getConnectingPoint()	{
		return connectingPoint;
	}

	public LinkedList<TAttribute> getAttributes()	{
		return myAttributes;
	}
}