/**
* Copyright (C) 2005 - 2014 Eric Van Dewoestine
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.eclim.plugin.jdt.command.src;
import java.io.File;
import java.util.ArrayList;
import org.eclim.annotation.Command;
import org.eclim.command.CommandLine;
import org.eclim.command.Options;
import org.eclim.plugin.core.command.AbstractCommand;
import org.eclim.plugin.jdt.util.JavaUtils;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.formatter.CodeFormatter;
/**
* Command to generate a new Java Type file
*
* @author Daniel Leong, Eric Van Dewoestine
*/
@Command(
name = "java_new",
options =
"REQUIRED p project ARG," +
"REQUIRED t type ARG," +
"REQUIRED n name ARG," +
"OPTIONAL r root ARG"
)
public class NewCommand
extends AbstractCommand
{
static final String TEMPLATE =
"package %1$s;\n\n" +
"public %2$s %3$s {\n" +
"}";
@Override
public Object execute(CommandLine commandLine)
throws Exception
{
String projectName = commandLine.getValue(Options.PROJECT_OPTION);
String type = commandLine.getValue(Options.TYPE_OPTION);
String name = commandLine.getValue(Options.NAME_OPTION);
String srcRoot = commandLine.getValue(Options.ROOT_OPTION);
// handle someone typing a file path instead of a fully qualified class name
if (name.endsWith(".java")){
name = name.substring(0, name.length() - 5);
}
name = name.replace('/', '.');
int classStart = name.lastIndexOf('.');
final String packageName = classStart >= 0 ?
name.substring(0, classStart) : name;
final String typeName = classStart >= 0 ?
name.substring(classStart + 1) : name;
final String fileName = typeName + ".java";
IJavaProject javaProject = JavaUtils.getJavaProject(projectName);
ArrayList<IPackageFragmentRoot> roots =
new ArrayList<IPackageFragmentRoot>();
// find all roots the requested package is found in.
for (IPackageFragment f : javaProject.getPackageFragments()) {
if (f.getElementName().equals(packageName)){
IJavaElement parent = f.getParent();
while (parent != null){
if (parent instanceof IPackageFragmentRoot){
IPackageFragmentRoot root = (IPackageFragmentRoot)parent;
if (root.getKind() == IPackageFragmentRoot.K_SOURCE){
roots.add(root);
}
break;
}
parent = parent.getParent();
}
}
}
// the package isn't found in any roots
if (roots.size() == 0){
// no root supplied, so we have to add all src roots to a list for the
// user to choose from.
for (IPackageFragmentRoot root : javaProject.getPackageFragmentRoots()){
if (root.getKind() == IPackageFragmentRoot.K_SOURCE){
roots.add(root);
}
}
}
// still no source roots, so we have to fail
if (roots.size() == 0){
throw new RuntimeException("No project source directories found.");
}
if (roots.size() > 1){
// user chosen root supplied, so grab that one.
if (srcRoot != null){
roots.clear();
for (IPackageFragmentRoot root : javaProject.getPackageFragmentRoots()){
if (root.getKind() == IPackageFragmentRoot.K_SOURCE &&
getPath(root).equals(srcRoot))
{
roots.add(root);
break;
}
}
if (roots.size() == 0){
throw new RuntimeException(
"Unable to find project source directory: " + srcRoot);
}
}
if (roots.size() > 1){
ArrayList<String> srcRoots = new ArrayList<String>();
for (IPackageFragmentRoot root : roots){
srcRoots.add(getPath(root));
}
return srcRoots;
}
}
IPackageFragmentRoot root = roots.get(0);
IPackageFragment fragment =
root.createPackageFragment(packageName, false, null);
// locate the to-be created file
File fragmentPath = fragment.getUnderlyingResource()
.getLocation().toFile();
final File file = new File(fragmentPath, fileName);
// make sure eclipse is up to date, in case the user
// deleted the file outside of eclipse's knowledge
fragment.getUnderlyingResource()
.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
// create!
final String content = String.format(TEMPLATE,
packageName, getType(type), typeName);
// NB: If we delete the file outside of Eclipse'
// awareness, it will whine if we then try to
// recreate it. So, if we *know* the file doesn't
// exist, force it.
ICompilationUnit unit = fragment.createCompilationUnit(
fileName,
content,
false,
new NullProgressMonitor());
if (unit == null || !file.exists()) {
throw new RuntimeException("Could not create " + file);
}
JavaUtils.format(
unit, CodeFormatter.K_COMPILATION_UNIT,
0, unit.getBuffer().getLength());
return file.getAbsolutePath();
}
private String getType(String type)
{
if ("abstract".equals(type)) {
return "abstract class";
}
return type;
}
private String getPath(IPackageFragmentRoot root)
throws Exception
{
return root.getRawClasspathEntry().getPath().toString();
}
}