/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.java.generation;
import java.io.File;
import java.util.Properties;
import java.util.StringTokenizer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.text.edits.TextEdit;
import org.jboss.tools.common.model.XModelObjectConstants;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
public class JavaBeanGenerator {
public static String PARAM_PACKAGENAME = "packageName"; //$NON-NLS-1$
public static String PARAM_SHORTNAME = "shortName"; //$NON-NLS-1$
public static String PARAM_ACCESS = "access"; //$NON-NLS-1$
public static String PARAM_EXTENDS = "extends"; //$NON-NLS-1$
public static String PARAM_IMPLEMENTS = "implements"; //$NON-NLS-1$
public static String PARAM_INTERFACE = "interface"; //$NON-NLS-1$
public static String ATT_CLASS_NAME = "class name"; //$NON-NLS-1$
public static String ATT_ACCESS_MODIFIER = "access modifier"; //$NON-NLS-1$
protected XModelObject context;
protected Properties input;
public void setContext(XModelObject context) {
this.context = context;
}
public void setInput(Properties input) {
this.input = input;
}
public IJavaProject getJavaProject() {
IProject project = EclipseResourceUtil.getProject(context);
return EclipseResourceUtil.getJavaProject(project);
}
public void generate() throws CoreException {
IJavaProject javaproject = getJavaProject();
if(javaproject == null) return;
String srcpath = getSrcLocation(javaproject);
if(srcpath == null) return;
String qclsname = input.getProperty(ATT_CLASS_NAME);
String filepath = srcpath + XModelObjectConstants.SEPARATOR + qclsname.replace('.', '/') + ".java"; //$NON-NLS-1$
if(new File(filepath).exists()) return;
int lastDot = qclsname.lastIndexOf('.');
Properties p = new Properties();
p.setProperty(PARAM_SHORTNAME, qclsname.substring(lastDot + 1));
p.setProperty(PARAM_PACKAGENAME, (lastDot < 0) ? "" : qclsname.substring(0, lastDot)); //$NON-NLS-1$
// String pkgname = (lastDot < 0) ? "" : qclsname.substring(0, lastDot);
String access = input.getProperty(ATT_ACCESS_MODIFIER);
if(access == null || "default".equals(access)) access = ""; //$NON-NLS-1$ //$NON-NLS-2$
p.setProperty(PARAM_ACCESS, access);
p.setProperty(PARAM_EXTENDS, input.getProperty("extends")); //$NON-NLS-1$
p.setProperty(PARAM_IMPLEMENTS, input.getProperty("implements").replace(';', ',')); //$NON-NLS-1$
p.setProperty(PARAM_INTERFACE, input.getProperty("interface").replace(';', ',')); //$NON-NLS-1$
doGenerateJava(javaproject, filepath, p);
}
private String getSrcLocation(IJavaProject javaproject) throws CoreException {
IClasspathEntry[] entries = javaproject.getResolvedClasspath(true);
for (int i = 0; i < entries.length; i++) {
if(entries[i].getEntryKind() != IClasspathEntry.CPE_SOURCE) continue;
IResource resource = null;
IPath projectPath = ModelPlugin.getWorkspace().getRoot().getFullPath();
if (projectPath!=null && projectPath.equals(projectPath.append(entries[i].getPath()))) {
resource = ModelPlugin.getWorkspace().getRoot();
} else {
resource = ModelPlugin.getWorkspace().getRoot().getFolder(entries[i].getPath());
}
return resource.getLocation().toString();
}
return null;
}
private void doGenerateJava(IJavaProject javaproject, String filepath, Properties p) throws CoreException {
IPackageFragmentRoot root = getJavaProjectSrcRoot(javaproject);
String pkgname = p.getProperty(PARAM_PACKAGENAME);
IPackageFragment pack = root.getPackageFragment(pkgname);
if(!pack.exists()) {
pack= root.createPackageFragment(pkgname, true, null);
}
String shortname = p.getProperty(PARAM_SHORTNAME);
String lineDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
ICompilationUnit parentCU = pack.createCompilationUnit(shortname + ".java", "", false, null); //$NON-NLS-1$ //$NON-NLS-2$
ICompilationUnit createdWorkingCopy = (ICompilationUnit) parentCU.getWorkingCopy(null);
/// imports= new ImportsStructure(createdWorkingCopy, prefOrder, threshold, false);
/// imports.addImport(pack.getElementName(), getTypeName());
String typeContent = constructTypeStub(p, lineDelimiter);
String cuContent= buildClassContent(parentCU, shortname, typeContent, lineDelimiter);
createdWorkingCopy.getBuffer().setContents(cuContent);
IType createdType = createdWorkingCopy.getType(shortname);
/// imports.create(false, new SubProgressMonitor(monitor, 1));
ICompilationUnit cu = createdType.getCompilationUnit();
synchronized(cu) {
cu.reconcile(ICompilationUnit.NO_AST, true, null, null);
}
/// imports.create(false, new SubProgressMonitor(monitor, 1));
/// synchronized(cu) {
/// cu.reconcile();
/// }
ISourceRange range = createdType.getSourceRange();
IBuffer buf = cu.getBuffer();
String originalContent= buf.getText(range.getOffset(), range.getLength());
String formattedContent = codeFormat2(CodeFormatter.K_CLASS_BODY_DECLARATIONS, originalContent, 0, lineDelimiter, cu.getJavaProject());
buf.replace(range.getOffset(), range.getLength(), formattedContent);
cu.commitWorkingCopy(false, null);
}
private String buildClassContent(ICompilationUnit cls, String shortname, String typeContent, String lineDelimiter) throws CoreException {
StringBuffer qName = new StringBuffer();
qName.append(shortname);
String comments = CodeGeneration.getTypeComment(cls, qName.toString(), lineDelimiter);
IPackageFragment p = (IPackageFragment)cls.getParent();
String content = CodeGeneration.getCompilationUnitContent(cls, comments, typeContent, lineDelimiter);
if (content != null) {
ASTParser parser = ASTParser.newParser(AST.JLS2);
parser.setSource(content.toCharArray());
CompilationUnit unit = (CompilationUnit) parser.createAST(null);
if ((p.isDefaultPackage() || unit.getPackage() != null) && !unit.types().isEmpty()) {
return content;
}
}
StringBuffer sb = new StringBuffer();
if(!p.isDefaultPackage()) {
sb.append("package "); //$NON-NLS-1$
sb.append(p.getElementName());
sb.append(';');
}
for (int i = 0; i < 2; i++) sb.append(lineDelimiter);
if(comments != null) {
sb.append(comments);
sb.append(lineDelimiter);
}
sb.append(typeContent);
return sb.toString();
}
public static String codeFormat2(int kind, String sourceString, int indentationLevel, String lineSeparator, IJavaProject project) {
TextEdit edit = ToolFactory.createCodeFormatter(project.getOptions(true)).format(kind, sourceString, 0, sourceString.length(), indentationLevel, lineSeparator);
Document doc = new Document(sourceString);
try {
edit.apply(doc, 0);
return doc.get();
} catch (BadLocationException e) {
return sourceString;
}
}
public static IPackageFragmentRoot getJavaProjectSrcRoot(IJavaProject javaProject) throws CoreException {
IClasspathEntry[] es = javaProject.getResolvedClasspath(true);
for (int i = 0; i < es.length; i++) {
if(es[i].getEntryKind() != IClasspathEntry.CPE_SOURCE) continue;
return javaProject.getPackageFragmentRoot(ModelPlugin.getWorkspace().getRoot().getFolder(es[i].getPath()));
}
return null;
}
private String constructTypeStub(Properties p, String lineDelimiter) {
StringBuffer sb = new StringBuffer();
// String pkgname = p.getProperty(PARAM_PACKAGENAME);
String access = p.getProperty(PARAM_ACCESS);
if(access == null) access = ""; else if(access.length() > 0) access += " "; //$NON-NLS-1$ //$NON-NLS-2$
boolean isInterface = XModelObjectConstants.TRUE.equals(p.getProperty(PARAM_INTERFACE));
String kind = isInterface ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
String shortname = p.getProperty(PARAM_SHORTNAME);
String _extends = p.getProperty(PARAM_EXTENDS);
if(_extends == null) _extends = ""; else if(_extends.length() > 0) _extends = "extends " + _extends + " "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
String _implements = formatImplements(p.getProperty(PARAM_IMPLEMENTS));
if(_implements == null) {
_implements = ""; //$NON-NLS-1$
} else if(_implements.length() > 0) {
if(isInterface) {
_implements = "extends " + _implements + " "; //$NON-NLS-1$ //$NON-NLS-2$
} else {
_implements = "implements " + _implements + " "; //$NON-NLS-1$ //$NON-NLS-2$
}
}
String header = access + kind + shortname + " " + _extends + _implements + "{" + lineDelimiter; //$NON-NLS-1$ //$NON-NLS-2$
sb.append(header);
if(!isInterface) {
sb.append("public " + shortname + "() {" + lineDelimiter + "}" + lineDelimiter); // constructor //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
sb.append("}" + lineDelimiter); //$NON-NLS-1$
return sb.toString();
}
private String formatImplements(String s) {
StringBuffer sb = new StringBuffer();
StringTokenizer st = new StringTokenizer(s, ",;"); //$NON-NLS-1$
while(st.hasMoreTokens()) {
sb.append(st.nextToken());
if(st.hasMoreTokens()) sb.append(", "); //$NON-NLS-1$
}
return sb.toString();
}
}