/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.javaparser;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;
import java.util.logging.Logger;
import org.openflexo.foundation.Inspectors;
import org.openflexo.foundation.dm.DMClassLibrary;
import org.openflexo.toolbox.FileUtils;
import com.thoughtworks.qdox.model.AbstractJavaEntity;
import com.thoughtworks.qdox.model.ClassLibrary;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaSource;
public class FJPJavaSource extends FJPJavaElement {
private static final Logger logger = Logger.getLogger(FJPJavaSource.class.getPackage().getName());
private final JavaParser _javaParser;
private final JavaSource _qdSource;
private final String _sourceCode;
private final String _fileName;
private FJPImportDeclarations _importDeclarations;
private FJPPackageDeclaration _packageDeclaration;
public FJPJavaSource(File sourceFile, ClassLibrary classLibrary) throws FileNotFoundException, IOException {
this(sourceFile, new JavaParser(classLibrary));
}
public FJPJavaSource(String sourceName, String sourceString, ClassLibrary classLibrary) {
this(sourceName, sourceString, new JavaParser(classLibrary));
}
public FJPJavaSource(File sourceFile, JavaParser javaParser) throws FileNotFoundException, IOException {
super(null);
_javaParser = javaParser;
_qdSource = javaParser.parseFileForSource(sourceFile, this);
javaSource = this;
_sourceCode = FileUtils.fileContents(sourceFile);
_fileName = sourceFile.getName();
init();
}
public FJPJavaSource(String sourceName, String sourceString, JavaParser javaParser) {
super(null);
_javaParser = javaParser;
_qdSource = javaParser.parseStringForSource(sourceString, this, sourceName);
javaSource = this;
_sourceCode = sourceString;
_fileName = sourceName;
init();
}
@Override
public JavaParser getJavaParser() {
return _javaParser;
}
// private Hashtable<AbstractJavaEntity,FJPJavaElement> _elements;
private Hashtable<String, FJPJavaElement> _classesElements;
private Hashtable<String, FJPJavaElement> _methodsElements;
private Hashtable<String, FJPJavaElement> _fieldsElements;
private void init() {
// _elements = new Hashtable<AbstractJavaEntity,FJPJavaElement>();
_classesElements = new Hashtable<String, FJPJavaElement>();
_methodsElements = new Hashtable<String, FJPJavaElement>();
_fieldsElements = new Hashtable<String, FJPJavaElement>();
for (JavaClass aClass : _qdSource.getClasses()) {
registerClass(aClass);
}
_packageDeclaration = new FJPPackageDeclaration();
_importDeclarations = new FJPImportDeclarations();
}
private void registerClass(JavaClass aClass) {
// Date date1 = new Date();
FJPJavaClass newJavaClass = new FJPJavaClass(aClass, this);
// Date date01 = new Date();
registerElements(aClass, newJavaClass);
// Date date02 = new Date();
// logger.info("Time1 : "+(date02.getTime()-date01.getTime())+" ms");
// t1 = 0;
// t2 = 0;
// t3 = 0;
// t4 = 0;
for (JavaMethod aMethod : aClass.getMethods()) {
registerMethod(aMethod);
}
// Date date03 = new Date();
// logger.info("Time2 : "+(date03.getTime()-date02.getTime())+" ms t1="+t1+" t2="+t2+" t3="+t3+" t4="+t4);
for (JavaField aField : aClass.getFields()) {
registerField(aField);
}
// Date date04 = new Date();
// logger.info("Time3 : "+(date04.getTime()-date03.getTime())+" ms");
for (JavaClass aNestedClass : aClass.getNestedClasses()) {
registerClass(aNestedClass);
}
// Date date2 = new Date();
// logger.info("Time4 : "+(date2.getTime()-date04.getTime())+" ms");
// logger.info("Time for registerClass("+aClass.getName()+") : "+(date2.getTime()-date1.getTime())+" ms");
}
/*private long t1 = 0;
private long t2 = 0;
private long t3 = 0;
private long t4 = 0;*/
private void registerMethod(JavaMethod aMethod) {
// Date date1 = new Date();
FJPJavaMethod newJavaMethod = new FJPJavaMethod(aMethod, this);
// Date date2 = new Date();
registerElements(aMethod, newJavaMethod);
// Date date3 = new Date();
// aMethod.hashCode();
// Date date4 = new Date();
// aMethod.getCallSignature();
// Date date5 = new Date();
// t1 += (date2.getTime()-date1.getTime());
// t2 += (date3.getTime()-date2.getTime());
// t3 += (date4.getTime()-date3.getTime());
// t4 += (date5.getTime()-date4.getTime());
}
private void registerField(JavaField aField) {
FJPJavaField newJavaField = new FJPJavaField(aField, this);
registerElements(aField, newJavaField);
}
/**
* Implementation of hashCode() method for JavaMethod in QDox library is unexpectedally very very slow. Consequence of that was that
* managing hashtable structures with JavaMethod keys was a very bad idea and resulted to very poor performances. I replaced this by a
* String key, obtained by following computing, and used in hashtable structures
*
* @param entity
* @return
*/
private String keyFor(AbstractJavaEntity entity) {
if (entity instanceof JavaClass) {
return ((JavaClass) entity).getPackage() + "." + ((JavaClass) entity).getName();
} else if (entity instanceof JavaMethod) {
return keyFor(((JavaMethod) entity).getParentClass()) + "." + ((JavaMethod) entity).getCallSignature();
}
if (entity instanceof JavaField) {
return keyFor((JavaClass) ((JavaField) entity).getParent()) + "." + ((JavaField) entity).getName();
}
return null;
}
private void registerElements(AbstractJavaEntity entity, FJPJavaElement element) {
if (entity instanceof JavaClass) {
_classesElements.put(keyFor(entity), element);
} else if (entity instanceof JavaMethod) {
_methodsElements.put(keyFor(entity), element);
} else if (entity instanceof JavaField) {
_fieldsElements.put(keyFor(entity), element);
} else {
logger.warning("Inconsistant data in registerElements() " + entity);
}
// _elements.put(entity, element);
}
@Override
public FJPJavaElement getFJPJavaElement(AbstractJavaEntity entity) {
if (entity == null) {
return null;
}
if (entity instanceof JavaClass) {
return _classesElements.get(keyFor(entity));
} else if (entity instanceof JavaMethod) {
return _methodsElements.get(keyFor(entity));
} else if (entity instanceof JavaField) {
return _fieldsElements.get(keyFor(entity));
} else {
logger.warning("Inconsistant data in registerElements() " + entity);
return null;
}
// return _elements.get(abstractJavaEntity);
}
@Override
public FJPJavaClass getClass(JavaClass aClass) {
return (FJPJavaClass) getFJPJavaElement(aClass);
}
@Override
public FJPJavaMethod getMethod(JavaMethod aMethod) {
return (FJPJavaMethod) getFJPJavaElement(aMethod);
}
@Override
public FJPJavaField getField(JavaField aField) {
return (FJPJavaField) getFJPJavaElement(aField);
}
public String getSourceCode() {
return _sourceCode;
}
@Override
protected FJPJavaClass[] retrieveClasses(JavaClass[] someClasses) {
if (someClasses == null) {
return new FJPJavaClass[0];
}
Vector<FJPJavaClass> vector = new Vector<FJPJavaClass>();
for (JavaClass c : someClasses) {
vector.add((FJPJavaClass) getFJPJavaElement(c));
}
return vector.toArray(new FJPJavaClass[vector.size()]);
}
@Override
protected FJPJavaMethod[] retrieveMethods(JavaMethod[] someMethods) {
if (someMethods == null) {
return new FJPJavaMethod[0];
}
Vector<FJPJavaMethod> vector = new Vector<FJPJavaMethod>();
for (JavaMethod m : someMethods) {
vector.add((FJPJavaMethod) getFJPJavaElement(m));
}
return vector.toArray(new FJPJavaMethod[vector.size()]);
}
@Override
protected FJPJavaField[] retrieveFields(JavaField[] someFields) {
if (someFields == null) {
return new FJPJavaField[0];
}
Vector<FJPJavaField> vector = new Vector<FJPJavaField>();
for (JavaField f : someFields) {
vector.add((FJPJavaField) getFJPJavaElement(f));
}
return vector.toArray(new FJPJavaField[vector.size()]);
}
private FJPJavaClass[] _classes;
public FJPJavaClass[] getClasses() {
if (_classes == null) {
_classes = retrieveClasses(_qdSource.getClasses());
}
return _classes;
}
public FJPJavaClass getRootClass() {
return getClasses()[0];
}
@Override
public DMClassLibrary getClassLibrary() {
return (DMClassLibrary) _qdSource.getClassLibrary();
}
@Override
public String getClassNamePrefix() {
return _qdSource.getClassNamePrefix();
}
public String[] getImports() {
return _qdSource.getImports();
}
public String getPackage() {
return _qdSource.getPackage();
}
public String getFileName() {
return _fileName;
}
@Override
public String getInspectorName() {
return Inspectors.CG.JAVA_SOURCE_INSPECTOR;
}
public class FJPImportDeclarations extends FJPJavaElement {
private final Vector<FJPImportDeclaration> _importDeclarations;
public FJPImportDeclarations() {
super(FJPJavaSource.this);
_importDeclarations = new Vector<FJPImportDeclaration>();
for (String i : getImports()) {
_importDeclarations.add(new FJPImportDeclaration(i));
}
}
@Override
public String getInspectorName() {
return Inspectors.CG.JAVA_IMPORTS_INSPECTOR;
}
public class FJPImportDeclaration extends FJPJavaElement {
private final String _importDeclaration;
private FJPImportDeclaration(String importDeclaration) {
super(FJPJavaSource.this);
_importDeclaration = importDeclaration;
}
public String getImportDeclaration() {
return _importDeclaration;
}
/*public Icon getIcon()
{
return CGIconLibrary.FJP_IMPORT_ICON;
}*/
@Override
public String getInspectorName() {
return Inspectors.CG.JAVA_IMPORT_INSPECTOR;
}
}
public Vector<FJPImportDeclaration> getImportDeclarations() {
return _importDeclarations;
}
}
public FJPImportDeclarations getImportDeclarations() {
return _importDeclarations;
}
public class FJPPackageDeclaration extends FJPJavaElement {
private FJPPackageDeclaration() {
super(FJPJavaSource.this);
}
public String getPackage() {
return FJPJavaSource.this.getPackage();
}
@Override
public String getInspectorName() {
return Inspectors.CG.JAVA_PACKAGE_INSPECTOR;
}
}
public FJPPackageDeclaration getPackageDeclaration() {
return _packageDeclaration;
}
public JavaSource getQDSource() {
return _qdSource;
}
}