Eclipse-PyUML/pyUml/src/pyUML/backend/ParseHelpers.java

195 lines
6.1 KiB
Java
Executable File

package pyUML.backend;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Model;
import org.python.pydev.parser.jython.ast.Name;
import org.python.pydev.parser.jython.ast.Num;
import org.python.pydev.parser.jython.ast.Str;
import org.python.pydev.parser.jython.ast.exprType;
import pyUML.pythonTree.PythonTreeFile;
import pyUML.pythonTree.PythonTreePackage;
import pyUML.pythonTree.PythonTreeRoot;
/**
* Some Helper methods needed for parsing Pything Code
* and handling the Python Abstract Syntax Tree
*/
public class ParseHelpers {
/**
* Reads out a file and returns the file content as a string
*
* @param file the file to read
* @return a String representing the file's content
* null on Error
*/
public static String fileToString(File file, IProject project) {
IFile iFile = EclipseHelperMethods.createFile(file.getAbsolutePath(), project);
return EclipseHelperMethods.iFileToString(iFile);
}
/**
* (Re-)Writes a string to a file and updates the file in the project,
* if the project is != null
* @param file the file to write to
* @param str the String to write to the File
* @param project (optional) the project where the file is located in
*/
public static void stringToFile(File file, String str, IProject project) {
try {
file.createNewFile();
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.write(str);
writer.close();
EclipseHelperMethods.updateFile(file.getAbsolutePath(), project);
}catch (IOException e) {
MessageDialog.openError(null, "IOException",
"Error writing to file "+ file.getPath());
e.printStackTrace();
}
}
/**
* Extracts a String representation of a python expression,
* if the expression is of type String or Num.
* The quotes of Strings are preserved
*
* @param expr The Python AST expression
* @param fileContent the content of the file where the expression
* is to be read
* @param attribute if true, expressions other than Strings or numbers are
* read by just reading the pure file content to the end of the line
* (or to a # sign). This works ONLY for attributes, not for expressions in
* function definitions.
* @param abbreviate if true, long values are abbreviated; at the end "(...)"
* is appended
* @param ONLY if this reads an attribute value: the value of the next line
* (needed to read multi-line attributes)
* if this is no attribute, this value is ignored.
*
* @return The String representation of this expression, null if expr is null
*/
public static String getStringOfExpr(exprType expr, PythonTreeFile pyFile, boolean attribute, boolean abbreviate, int nextLine){
if (expr == null)
return null;
String exprString;
if (expr instanceof Str) {
Str defaultValStr = (Str) expr;
exprString = defaultValStr.s;
if (defaultValStr.type == Str.SingleDouble) {
exprString = "\"" + exprString + "\"";
}
else if (defaultValStr.type == Str.SingleSingle) {
exprString = "'" + exprString + "'";
}
} else if (expr instanceof Name) {
Name defaultValNum = (Name) expr;
exprString = defaultValNum.id;
} else if (expr instanceof Num) {
Num defaultValNum = (Num) expr;
exprString = defaultValNum.num;
} else if (attribute){
exprString = readExprAsText(expr, pyFile, nextLine);
} else {
return GlobalConstants.getUnknownExpression();
}
// cut default value, if it is too long
if (abbreviate && exprString.length() > 19) {
exprString = exprString.substring(0,14) + "(...)";
}
return exprString;
}
/**
* Helper method for getStringOfExpr()
* Can read a multi-line-expression of an attribute
*
* @param expr
* @param pyFile
* @param nextLine
* @return
*/
public static String readExprAsText(exprType expr, PythonTreeFile pyFile, int nextLine) {
String[] lines = pyFile.getSplittedFileContent();
String exprString = lines[expr.beginLine-1];
exprString = exprString.substring(exprString.indexOf("=")+1);
exprString = exprString.replaceAll("^[\\s]*","");
exprString = exprString.replaceAll(" # created by PyUML.*$", "");
exprString = exprString.replaceAll("[\\s]*$", "");
for (int i=expr.beginLine; i < nextLine - 1; i++) {
String line = lines[i];
// docString comments of static attributes have a wrong "beginLine" value
// -> manually define here to ignore docStrings!
if (line.matches("^[\\s]*\"\"\".*"))
break;
line = line.replaceAll("# created by PyUML.*$", "");
line = " " +line.replaceAll("^[\\s]*", "");
exprString += line;
exprString = exprString.replaceAll("[\\s]*$", "");
}
// if there are called other classes/packages, the index
// is on the value, not on the "a.b.c"-prefix.
// if that's the case, add the prefix afterwards:
return exprString;
}
/**
* Simple method to extract the XMI-ID out of a line
* containing the PyUML string "# PyUML: XMI_ID: ..."
* @param content
* @return
*/
public static String extractXmiFromString(String content) {
String xmi_id = null;
String[] lines = content.split("\n");
for (String line : lines) {
if (line.matches("\\s*# PyUML:.*")) {
String[] splittedLine = line.split("XMI_ID:");
if (splittedLine.length == 2) {
xmi_id = splittedLine[1];
}
}
}
return xmi_id;
}
/**
* This creates a string containing the model package structure as
* "/packSup/packSub/" , where the last package contains the
* current class.
* @param cl The class in the model to find the package structure for
* @return a string containing the parent package structure
* of this class
*
*/
public static String getModelPackageStructure(org.eclipse.uml2.uml.Type cl) {
org.eclipse.uml2.uml.Package pack = cl.getPackage();
String structure = "";
while (! (pack instanceof Model))
{
structure = "/"+pack.getName() + structure ;
pack = pack.getNestingPackage();
}
return structure + "/";
}
}