package pyUML.pythonTree; import java.io.File; import java.util.List; import java.util.Vector; import org.eclipse.core.runtime.IPath; import org.python.pydev.parser.jython.SimpleNode; import org.python.pydev.parser.jython.ast.ClassDef; import org.python.pydev.parser.jython.ast.Module; import org.python.pydev.parser.jython.ast.stmtType; import org.python.pydev.refactoring.ast.visitors.VisitorFactory; import pyUML.backend.EclipseHelperMethods; import pyUML.backend.ParseHelpers; import pyUML.exceptions.PyUMLCancelledException; import pyUML.exceptions.PyUMLParseException; /** * This class represents a Python file in the Python * Package structure. * It must have a parent package and contains a * pydev Abstract Syntax Tree (AST) * */ public class PythonTreeFile extends PythonTreeNode{ private IPath filePath; private PythonTreePackage parent; private SimpleNode ast; private List classesInFile; private String fileContent; private String[] splittedFileContent = null; public PythonTreeFile(IPath filePath, PythonTreePackage parent) throws PyUMLParseException, PyUMLCancelledException{ super(parent); this.filePath = filePath; this.parent = parent; this.name = filePath.lastSegment(); this.classesInFile = new Vector(); this.initAst(); this.initClassesWithAST(); } /** * Parses the given Python file and saves the ast */ private void initAst() throws PyUMLParseException{ // init AST so that it will never be null this.ast=new SimpleNode(); // try to get content of python file this.fileContent = ParseHelpers.fileToString( new File(filePath.toOSString()), this.getProject()); if (this.fileContent==null) { return; } // get AST of file try{ this.ast = VisitorFactory.getRootNodeFromString(this.fileContent); } catch (Throwable t) { String message = t.getClass().getName()+ " while parsing file " + this.filePath.toOSString() +"\n\n" +t.getMessage(); throw new PyUMLParseException(message); } } /** * extracts all the top level clases (no inner classes) * out of the AST */ private void initClassesWithAST() throws PyUMLParseException, PyUMLCancelledException{ if (this.ast instanceof Module) { Module pyModule = (Module) this.ast; stmtType[] statements = pyModule.body; for (int i = 0; i < statements.length; i++) { if (statements[i] instanceof ClassDef) { // get end line of class -> look for following statement int followingLine = 0; if (i +1 < statements.length) { stmtType followingStmt = statements[i+1]; followingLine = followingStmt.beginLine; } ClassDef pyClass = (ClassDef) statements[i]; PythonTreeClass cl = new PythonTreeClass(this.parent, this, pyClass, followingLine-1); this.classesInFile.add(cl); } } } } public void updateFileInEclipse() { EclipseHelperMethods.updateFile(this.getFilePath().toOSString(), this.getProject()); } /** * re-inits a file -> re-parses the content * and adds new classes, if needed. * @throws PyUMLParseException */ public void reInitFile() throws PyUMLParseException, PyUMLCancelledException { for (PythonTreeClass cl : this.getClassesInFile()) { this.getRoot().getClassDict().remove(cl.getPackageStructure()+cl.getName()); this.getRoot().getClassNameDict().remove(cl.getPackageStructure()+cl.getName()); this.getParent().getChildClasses().remove(cl); } this.splittedFileContent=null; this.classesInFile = new Vector(); this.initAst(); this.initClassesWithAST(); this.getParent().getChildClasses().addAll(this.getClassesInFile()); this.getRoot().getChildClasses().addAll(this.getParent().getChildClasses()); } /** * Splits the file content by "\n", which results in an array of lines. * The result is cached for performance reasons. * @return an Array containing the lines of the file content */ public String[] getSplittedFileContent() { if (splittedFileContent == null) splittedFileContent = fileContent.split("\n"); return splittedFileContent; } public IPath getFilePath() { return filePath; } public SimpleNode getAst() { return ast; } public PythonTreePackage getParent() { return parent; } public List getClassesInFile() { return classesInFile; } /** * @return the content of the whole file as a String */ public String getFileContent() { return fileContent; } /** * Set this objects "file content" string. This does *not* * update any real file! * @param fileContent the file content as a String */ public void setFileContent(String fileContent) { this.fileContent = fileContent; this.splittedFileContent=null; } public void setFilePath(IPath filePath) { this.filePath = filePath; } }