/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille * * ludovic.apvrille AT enst.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; import myutil.Conversion; import myutil.TraceManager; import translator.JKeyword; import translator.RTLOTOSKeyword; import translator.UPPAALKeyword; import ui.avatarbd.AvatarBDDataType; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Vector; /** * Class AvatarMethod * Method in Avatar ... * Creation: 08/04/2010 * * @author Ludovic APVRILLE * @version 1.0 08/04/2010 */ public class AvatarMethod { // Types of parameters public final static int NATURAL = 0; public final static int BOOLEAN = 1; public final static int INTEGER = 2; public final static int OTHER = 3; protected String id; protected String typeIds[]; protected String types[]; protected String returnType; protected boolean implementationProvided; public AvatarMethod(String _id, String _types[], String _typeIds[]) { id = _id; types = _types; typeIds = _typeIds; returnType = ""; implementationProvided = false; //TraceManager.addDev("(Cons) Implementation of " + this + " is now set to: " + implementationProvided); } public AvatarMethod(String _id, String _types[], String _typeIds[], String _returnType) { id = _id; types = _types; typeIds = _typeIds; returnType = _returnType; implementationProvided = false; //TraceManager.addDev("(Cons) Implementation of " + this + " is now set to: " + implementationProvided); } public boolean isImplementationProvided() { return implementationProvided; } public void setImplementationProvided(boolean _imp) { //TraceManager.addDev("Implementation of " + this + " is now set to: " + _imp); implementationProvided = _imp; } // An operation must be of the form: "id(type id0, type id1, ...)" // Or 'returntype id(type id0, type id1, ...)' // Returns null in case the method is not valid public static AvatarMethod isAValidMethod(String _method, List<String> extraTypes, boolean checkTypes) { //TraceManager.addDev("Is a valid method? " + _method); String method, tmp, id; String rt = ""; if (_method == null) { return null; } method = _method.trim(); // Must replace all "more than one space" by only one space method = Conversion.replaceAllString(method, "\t", " "); method = Conversion.replaceAllString(method, " ", " "); //TraceManager.addDev("Method=" + method); if (method.length() == 0) { return null; } // If has opening parenthesis, remove all spaces before int index0 = method.indexOf('('); int index1; index0 = method.indexOf('('); if (index0 != -1) { if (index0 == 0) { return null; } else if (method.charAt(index0 - 1) == ' ') { method = method.substring(0, index0 - 1) + method.substring(index0, method.length()); } } // Check whether there is a return type or not int index2 = method.indexOf(' '); if (index2 != -1) { tmp = method.substring(0, index2); // No parenthesis? if ((tmp.indexOf('(') == -1) && (tmp.indexOf(')') == -1)) { // So, there is a return type! rt = tmp.trim(); method = method.substring(index2 + 1, method.length()).trim(); if (!isAValidId(rt, false, false, false, checkTypes, extraTypes)) { TraceManager.addDev("Unvalid return type: " + rt); return null; } //TraceManager.addDev("Found a return type: " + rt); //TraceManager.addDev("Now working with method: " + method); } } //TraceManager.addDev("Valid type stage 1"); index0 = method.indexOf('('); index1 = method.indexOf(')'); // Only one of the two parenthesis if ((index0 == -1) && (index1 > -1)) { return null; } if ((index1 == -1) && (index0 > -1)) { return null; } // No parenthesis at all if ((index0 == -1) && (index1 == -1)) { if (isAValidId(method, true, true, true, checkTypes, extraTypes)) { return new AvatarMethod(method, new String[0], new String[0], rt); } else { return null; } } // Check parenthesis order if (index0 > index1) { return null; } // Check that only one parenthesis of each type tmp = method.substring(Math.min(index0 + 1, method.length()), method.length()); if (tmp.indexOf('(') > -1) { return null; } tmp = method.substring(Math.min(index1 + 1, method.length()), method.length()); if (tmp.indexOf(')') > -1) { return null; } // And so: parenthesis are in the right order, and are used only one for each //TraceManager.addDev("Checking for an id before parenthesis index0=" + index0 + " method=" + method); // Before parenthesis -> id tmp = method.substring(0, index0).trim(); //TraceManager.addDev("Checking for an id before parenthesis; tmp=" + tmp); if (!isAValidId(tmp, true, true, true, false, extraTypes)) { return null; } id = tmp; // Between parenthesis: parameters of the form: String space String comma // We replace double space by spaces and then spaces by commas tmp = method.substring(index0 + 1, index1).trim(); // no parameter? if (tmp.length() == 0) { return new AvatarMethod(id, new String[0], new String[0], rt); } // Has parameters... tmp = Conversion.replaceAllString(tmp, " ", " "); tmp = Conversion.replaceAllString(tmp, " ,", ","); tmp = Conversion.replaceAllString(tmp, ", ", ","); tmp = Conversion.replaceAllChar(tmp, ' ', ","); //TraceManager.addDev("tmp=" + tmp); String splitted[] = tmp.split(","); int size = splitted.length / 2; // TraceManager.addDev("Nb of parameters=" + size); String types[] = new String[size]; String typeIds[] = new String[size]; boolean b0, b1; int i; //TraceManager.addDev("splitted"); //for(i=0; i<splitted.length; i++) { // TraceManager.addDev("splitted[" + i + "]: " + splitted[i]); //} try { for (i = 0; i < splitted.length; i = i + 2) { if (splitted[i].length() == 0) { return null; } if (splitted[i + 1].length() == 0) { return null; } TraceManager.addDev("Checking input parameter"); if (!isAValidId(splitted[i], false, false,false, checkTypes, extraTypes)) { TraceManager.addDev("Unvalid input type #" + i + ": " + splitted[i]); return null; } if (!isAValidId(splitted[i + 1], true, true,true, false, extraTypes)) { TraceManager.addDev("Unvalid id of parameter " + splitted[i + 1]); return null; } //TraceManager.addDev("Adding parameter: " + splitted[i] + " " + splitted[i+1]); types[i / 2] = splitted[i]; typeIds[i / 2] = splitted[i + 1]; } } catch (Exception e) { TraceManager.addDev("AvatarMethod Exception:" + e.getMessage()); return null; } //TraceManager.addDev("Returning method"); return new AvatarMethod(id, types, typeIds, rt); } public String getId() { return id; } public String[] getTypes() { return types; } public String[] getTypeIds() { return typeIds; } public String getReturnType() { return returnType; } public String getType(int _index) { if ((_index < 0) || (_index >= types.length)) { return null; } return types[_index]; } public String getTypeId(int _index) { if ((_index < 0) || (_index >= typeIds.length)) { return null; } return typeIds[_index]; } public static boolean isAValidId(String id, boolean checkKeyword, boolean checkUPPAALKeyword, boolean checkJavaKeyword, boolean checkTypes, List<String> extraTypes) { // test whether _id is a word TraceManager.addDev("is valid with id=" + id); if ((id == null) || (id.length() < 1)) { return false; } String lowerid = id.toLowerCase(); boolean b1, b2, b3, b4, b5, b6; b1 = (id.substring(0, 1)).matches("[a-zA-Z]"); b2 = id.matches("\\w*"); if (checkKeyword) { b3 = !RTLOTOSKeyword.isAKeyword(lowerid); } else { b3 = true; } if (checkKeyword) { b6 = !UPPAALKeyword.isAKeyword(lowerid); } else { b6 = true; } if (checkJavaKeyword) { b5 = !JKeyword.isAKeyword(lowerid); } else { b5 = true; } if (checkTypes) { //TraceManager.addDev("Checking types with lowerid=" + lowerid); b4 = ((lowerid.equals(getStringType(INTEGER).toLowerCase())) || (lowerid.equals(getStringType(BOOLEAN).toLowerCase()))); //TraceManager.addDev("b4=" + b4 + " extraTypes=" + extraTypes); if ((extraTypes != null) && (b4 == false)){ //TraceManager.addDev("Checking extra types, with extraTypes = " + extraTypes); for(String type: extraTypes) { String typ = type.toLowerCase(); //TraceManager.addDev("Comparing type >" + typ + "< with >" + lowerid + "<"); if (type.toLowerCase().compareTo(lowerid) == 0) { //TraceManager.addDev("Similar type"); b4 = true; break; } } } } else { b4 = true; } return (b1 && b2 && b3 && b4 && b5 && b6); } public static boolean notIn(String s, Vector forbidden) { if (forbidden == null) { return true; } AvatarMethod am; for (int i = 0; i < forbidden.size(); i++) { am = (AvatarMethod) (forbidden.elementAt(i)); if (s.compareTo(am.getId()) == 0) { return false; } } return true; } public static int getType(String s) { if (s.equals("nat")) { return NATURAL; } else if (s.equals("bool")) { return BOOLEAN; } else if (s.equals("int")) { return INTEGER; } else if (s.equals("Integer")) { return INTEGER; } return OTHER; } public static String getStringType(int type) { switch (type) { case NATURAL: return "nat"; case BOOLEAN: return "bool"; case INTEGER: return "int"; } return ""; } public String toString() { int cpt = 0; String method = ""; if (returnType.length() > 0) { method += returnType + " "; } method += id + "("; for (int i = 0; i < types.length; i++) { method += types[i] + " " + typeIds[i]; if (i < (types.length - 1)) { method += ", "; } } method += ")"; return method; } public String toSaveString() { String ret = ""; if (implementationProvided) { //TraceManager.addDev("Implementation provided for " + toString()); ret += "$"; } return ret + toString(); } // Comparison on id only public boolean equals(Object o) { if (!(o instanceof AvatarMethod)) { return false; } AvatarMethod am = (AvatarMethod) o; return getId().equals(am.getId()); } public String getUseDescription() { String s = getId() + "("; for (int i = 0; i < typeIds.length; i++) { s += typeIds[i]; if (i < (typeIds.length - 1)) { s += ", "; } } s += ")"; return s; } public AvatarMethod makeClone() { AvatarMethod am = isAValidMethod(toString(), null, false); am.setImplementationProvided(isImplementationProvided()); return am; } }