diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml
new file mode 100644
index 0000000..2e82680
--- /dev/null
+++ b/META-INF/plugin.xml
@@ -0,0 +1,47 @@
+
+ If a test class already exists, your will be prompted to either
+ overwrite or compare the test class using diff panels.
+ ]]>
+
+ ]]>
+
Aug 30, 2003+ */ +public class Const { + public static final String RELATIVE_DIR_NAME = "resources"; + public static final String ENTRY_LIST_VAR_NAME = "entryList"; + public static final String TODAY_VAR_NAME = "today"; + public static final String TODAY_LONG_VAR_NAME = "todayLong"; + public static final String AUTHOR_VAR_NAME = "author"; + public static final String HAS_ANNOTATIONS_VAR_NAME = "hasAnnotations"; + public static final String TEMPLATE_NAME = "testnggen.vm"; + public static final String RESOURCE_LOADER_TYPE = "file"; + public static final String RESOURCE_LOADER_CLASS_KEY = "file.resource.loader.class"; + public static final String RESOURCE_LOADER_CLASS_VALUE = "org.apache.velocity.runtime.resource.loader.FileResourceLoader"; + public static final String PROPERTIES_FILE_NAME = "testnggen.properties"; + public static final String OUTPUT_KEY = "output"; + public static final String OVERWRITE_MSG = + "File already exists. Do you want to see the difference between the old and the new test cases?\n" + + "By answering 'No' you will overwrite an existing file."; + public static final String CLASS_NAME_VAR = "testClass"; + public static final String DATE_FORMAT_VAR = "dateFormat"; + + private Const() {} +} diff --git a/src/org/intellij/plugins/testnggen/FileCreator.java b/src/org/intellij/plugins/testnggen/FileCreator.java new file mode 100644 index 0000000..90dfbb5 --- /dev/null +++ b/src/org/intellij/plugins/testnggen/FileCreator.java @@ -0,0 +1,125 @@ +package org.intellij.plugins.testnggen; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileSystem; +import com.intellij.psi.PsiJavaFile; +import org.intellij.plugins.testnggen.diff.DiffFileAction; +import org.intellij.plugins.testnggen.util.GenUtil; + +import javax.swing.*; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringWriter; + + +/** + * Responsible for writing test case out to the file and bringing + * new editor window up. + * Must implement runnable since we are using Application.runWriteAction in + * TestNGGeneratorAction to refresh the content of the VirtualFileSystem. + * + * @author Alex Nazimok (SCI) + * @author Erik C. Thauvin + * @since
Sep 1, 2003+ */ +public class FileCreator implements Runnable { + private final String _outputFile; + private final StringWriter _writer; + private final DataContext _ctx; + private final PsiJavaFile _file; + private final GeneratorContext _genCtx; + private final boolean _overwrite; + + /** + * Default constructor + * @param outputFile output file name + * @param writer holds the content of the file + * @param genCtx generator context + */ + public FileCreator(String outputFile, StringWriter writer, GeneratorContext genCtx, boolean overwrite) { + _outputFile = outputFile + ".java"; + _writer = writer; + _ctx = genCtx.getDataContext(); + _file = genCtx.getFile(); + _genCtx = genCtx; + _overwrite = overwrite; + } + + /** + * When an object implementing interface
Runnable
is used
+ * to create a thread, starting the thread causes the object's
+ * run
method to be called in that separately executing
+ * thread.
+ *
+ * The general contract of the method run
is that it may
+ * take any action whatsoever.
+ *
+ * @see java.lang.Thread#run()
+ */
+ public final void run() {
+ final File newFile = new File(_outputFile);
+ int overwriteInd = JOptionPane.NO_OPTION;
+
+ if (!newFile.getParentFile().exists()) {
+ newFile.getParentFile().mkdirs();
+ }
+
+ if (newFile.exists() && !_overwrite) {
+ overwriteInd =
+ JOptionPane.showOptionDialog(null, Const.OVERWRITE_MSG, "View the difference?",
+ JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
+ }
+
+ if (JOptionPane.NO_OPTION == overwriteInd) {
+ FileWriter w = null;
+ try {
+ w = new FileWriter(newFile);
+ w.write(_writer.toString());
+ w.flush();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ finally {
+ if (w != null) {
+ try {
+ w.close();
+ }
+ catch (IOException ignore) {
+ ; // Do nothing
+ }
+ }
+ }
+
+ //Refresh and open new file in the editor
+ final Project project = GenUtil.getProject(_ctx);
+ final VirtualFileSystem vfs = _file.getVirtualFile().getFileSystem();
+
+ GenUtil.getLogger(getClass().getName()).info("OutputFile: " + _outputFile);
+ final VirtualFile fileToOpen = vfs.refreshAndFindFileByPath(_outputFile);
+
+ if(fileToOpen != null) {
+ FileEditorManager.getInstance(project).openFile(fileToOpen, true);
+ try {
+ // Demetra doesn't support this call, for some reason
+ vfs.forceRefreshFile(fileToOpen);
+ }
+ catch (NoSuchMethodError ignore) {
+ ; // Do nothing.
+ }
+ }
+ else {
+ throw new IllegalArgumentException("Unable to find: " + _outputFile);
+ }
+ }
+
+ else if (JOptionPane.YES_OPTION == overwriteInd) {
+ final VirtualFileSystem vfs = _file.getVirtualFile().getFileSystem();
+ DiffFileAction.showDiff(_writer.toString(), vfs.findFileByPath(_outputFile), _genCtx);
+ }
+ }
+}
diff --git a/src/org/intellij/plugins/testnggen/GeneratorContext.java b/src/org/intellij/plugins/testnggen/GeneratorContext.java
new file mode 100644
index 0000000..6d3c6f1
--- /dev/null
+++ b/src/org/intellij/plugins/testnggen/GeneratorContext.java
@@ -0,0 +1,58 @@
+package org.intellij.plugins.testnggen;
+
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiJavaFile;
+
+
+/**
+ * Data holder/distributer object.
+ *
+ * @author Alex Nazimok (SCI)
+ * @since
Sep 3, 2003+ */ +public class GeneratorContext { + private final DataContext _ctx; + private final PsiJavaFile _file; + private final PsiClass _psiClass; + private String _outputFileName; + + public GeneratorContext(DataContext ctx, PsiJavaFile file, PsiClass psiClass) { + _ctx = ctx; + _file = file; + _psiClass = psiClass; + } + + public final DataContext getDataContext() { + return _ctx; + } + + public final PsiJavaFile getFile() { + return _file; + } + + public final PsiClass getPsiClass() { + return _psiClass; + } + + public final String getPackageName() { + return _file.getPackageName(); + } + + public final String getClassName(boolean qualified) { + if (!qualified) { + return _psiClass.getName(); + } + else { + return _psiClass.getQualifiedName(); + } + } + + public final String getOutputFileName() { + return _outputFileName; + } + + public final void setOutputFileName(String outputFileName) { + _outputFileName = outputFileName; + } +} diff --git a/src/org/intellij/plugins/testnggen/TestNGGenerator.java b/src/org/intellij/plugins/testnggen/TestNGGenerator.java new file mode 100644 index 0000000..56c3d2c --- /dev/null +++ b/src/org/intellij/plugins/testnggen/TestNGGenerator.java @@ -0,0 +1,30 @@ +package org.intellij.plugins.testnggen; + +import com.intellij.openapi.components.ApplicationComponent; + + +/** + * ApplicationComponent implementation + * @author Alex Nazimok (SCI) + * @since
Aug 29, 2003+ */ +public class TestNGGenerator implements ApplicationComponent { + /** + * Method is called after plugin is already created and configured. Plugin can start to communicate with + * other plugins only in this method. + */ + public final void initComponent() {} + + /** + * This method is called on plugin disposal. + */ + public final void disposeComponent() {} + + /** + * Returns the name of component + * @return String representing component name. Use plugin_name.component_name notation. + */ + public final String getComponentName() { + return "TestNGGenerator.TestNGGenerator"; + } +} diff --git a/src/org/intellij/plugins/testnggen/TestNGGeneratorAction.java b/src/org/intellij/plugins/testnggen/TestNGGeneratorAction.java new file mode 100644 index 0000000..67a5c13 --- /dev/null +++ b/src/org/intellij/plugins/testnggen/TestNGGeneratorAction.java @@ -0,0 +1,31 @@ +package org.intellij.plugins.testnggen; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorAction; +import com.intellij.psi.PsiJavaFile; +import org.intellij.plugins.testnggen.util.GenUtil; + + +/** + * TestNGGenerator action implementation + * @author Alex Nazimok (SCI) + * @since
Aug 28, 2003+ */ +public class TestNGGeneratorAction extends EditorAction { + public TestNGGeneratorAction() { + super(new TestNGGeneratorActionHandler()); + } + + /** + * Enables Generate popup for Java files only. + * @param editor + * @param presentation + * @param dataContext + */ + public final void update(Editor editor, Presentation presentation, DataContext dataContext) { + final PsiJavaFile javaFile = GenUtil.getSelectedJavaFile(dataContext); + presentation.setEnabled(javaFile != null); + } +} diff --git a/src/org/intellij/plugins/testnggen/TestNGGeneratorActionHandler.java b/src/org/intellij/plugins/testnggen/TestNGGeneratorActionHandler.java new file mode 100644 index 0000000..2e708a2 --- /dev/null +++ b/src/org/intellij/plugins/testnggen/TestNGGeneratorActionHandler.java @@ -0,0 +1,207 @@ +package org.intellij.plugins.testnggen; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; +import com.intellij.psi.*; +import com.intellij.pom.java.LanguageLevel; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.intellij.plugins.testnggen.util.GenUtil; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + + +/** + * This is where the magic happens. + * + * @author Alex Nazimok (SCI) + * @author Erik C. Thauvin + * @since
Sep 3, 2003+ * @noinspection InnerClassMayBeStatic + */ +public class TestNGGeneratorActionHandler extends EditorWriteActionHandler { + private static final Logger logger = GenUtil.getLogger(TestNGGeneratorActionHandler.class.getName()); + private List entryList; + private GeneratorContext genCtx; + + /** + * Executed upon action in the Editor + * + * @param editor IDEA Editor + * @param dataContext DataCOntext + */ + public final void executeWriteAction(Editor editor, DataContext dataContext) { + final PsiJavaFile file = GenUtil.getSelectedJavaFile(dataContext); + + if (file == null) { + return; + } + + final PsiClass[] psiClasses = file.getClasses(); + + if (psiClasses == null) { + return; + } + + for (int i = 0; i < psiClasses.length; i++) { + if ((psiClasses[i] != null) && (psiClasses[i].getQualifiedName() != null)) { + genCtx = new GeneratorContext(dataContext, file, psiClasses[i]); + entryList = new ArrayList(0); + + try { + if (psiClasses[i] == null) { + return; + } + + if (!psiClasses[i].isInterface()) { + final List methodList = new ArrayList(0); + final List fieldList = new ArrayList(0); + + buildMethodList(psiClasses[i].getMethods(), methodList); + buildFieldList(psiClasses[i].getFields(), fieldList); + + final PsiClass[] innerClass = psiClasses[i].getAllInnerClasses(); + + for (int idx = 0; idx < innerClass.length; idx++) { + buildMethodList(innerClass[idx].getMethods(), methodList); + buildFieldList(psiClasses[i].getFields(), fieldList); + } + + entryList.add(new TemplateEntry(genCtx.getClassName(false), + genCtx.getPackageName(), + methodList, + fieldList)); + process(); + } + } + catch (Exception e) { + GenUtil.getLogger(getClass().getName()).error(e); + } + } + } + } + + /** + * Builds a list of class scope fields from an array of PsiFields + * @param fields an array of fields + * @param fieldList list to be populated + */ + private static void buildFieldList(PsiField[] fields, List fieldList) { + for(int i = 0; i < fields.length; i++){ + fieldList.add(fields[i].getName()); + } + } + + /** + * Builds method List from an array of PsiMethods + * + * @param methods array of methods + * @param methodList list to be populated + */ + private static void buildMethodList(PsiMethod[] methods, List methodList) { + for (int j = 0; j < methods.length; j++) { + if (!methods[j].isConstructor()) { + final PsiModifierList modifiers = methods[j].getModifierList(); + + if (!modifiers.hasModifierProperty("private")) { + final String methodName = methods[j].getName(); + + if (!methodList.contains(methodName)) { + methodList.add(methodName); + } + else { + for (int k = 1; k < methods.length; k++) { + if (!methodList.contains(methodName + k)) { + methodList.add(methodName + k); + + break; + } + } + } + } + } + } + } + + /** + * Sets all the needed vars in VelocityContext and + * merges the template + */ + private void process() { + try { + final Properties velocityProperties = new Properties(); + velocityProperties.setProperty(VelocityEngine.RESOURCE_LOADER, Const.RESOURCE_LOADER_TYPE); + velocityProperties.setProperty(Const.RESOURCE_LOADER_CLASS_KEY, Const.RESOURCE_LOADER_CLASS_VALUE); + velocityProperties.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, + GenUtil.getResourcePath(Const.RELATIVE_DIR_NAME)); + + final VelocityContext context = new VelocityContext(); + context.put(Const.ENTRY_LIST_VAR_NAME, entryList); + context.put(Const.TODAY_VAR_NAME, GenUtil.formatDate("MM/dd/yyyy")); + context.put(Const.TODAY_LONG_VAR_NAME, GenUtil.formatDate("MMMM d, yyyy")); + context.put(Const.AUTHOR_VAR_NAME, System.getProperty("user.name", "")); + + final LanguageLevel level = PsiManager.getInstance(GenUtil.getProject(genCtx.getDataContext())).getEffectiveLanguageLevel(); + final boolean hasAnnotations = !(level == LanguageLevel.JDK_1_4 || level == LanguageLevel.JDK_1_3); + context.put(Const.HAS_ANNOTATIONS_VAR_NAME, Boolean.valueOf(hasAnnotations)); + + + final VelocityEngine ve = new VelocityEngine(); + ve.init(velocityProperties); + + final Template template = ve.getTemplate(Const.TEMPLATE_NAME); + final StringWriter writer = new StringWriter(); + template.merge(context, writer); + genCtx.setOutputFileName((String) context.get(Const.CLASS_NAME_VAR)); + ApplicationManager.getApplication().runWriteAction(new FileCreator(GenUtil.getOutputFile(genCtx, + genCtx.getOutputFileName()), writer, genCtx, false)); + } + catch (Exception e) { + logger.error(e); + } + } + + /** + * DataHolder class. Needs to be public since velocity is using it in the + * template. + * @noinspection CanBeStatic,PublicInnerClass,NonStaticInnerClassInSecureContext + */ + public class TemplateEntry { + private List _methodList = new ArrayList(0); + private List _fieldList = new ArrayList(0); + + private final String _className; + private final String _packageName; + + + public TemplateEntry(String className, String packageName, List methodList, List fieldList) { + _className = className; + _packageName = packageName; + _methodList = methodList; + _fieldList = fieldList; + } + + public final String getClassName() { + return _className; + } + + public final String getPackageName() { + return _packageName; + } + + public final List getMethodList() { + return _methodList; + } + + public final List getFieldList() { + return _fieldList; + } + } +} diff --git a/src/org/intellij/plugins/testnggen/diff/DiffFileAction.java b/src/org/intellij/plugins/testnggen/diff/DiffFileAction.java new file mode 100644 index 0000000..31aa950 --- /dev/null +++ b/src/org/intellij/plugins/testnggen/diff/DiffFileAction.java @@ -0,0 +1,62 @@ +package org.intellij.plugins.testnggen.diff; + +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.actionSystem.DataConstants; +import org.intellij.plugins.testnggen.GeneratorContext; + +import java.io.IOException; + + +public final class DiffFileAction { + /** + * Disables the default constructor. + * + * @throws UnsupportedOperationException if the constructor is called. + */ + private DiffFileAction() throws UnsupportedOperationException { + throw new UnsupportedOperationException("Illegal constructor call."); + } + + public static void showDiff(String paneTwoContents, VirtualFile paneTwoFile, GeneratorContext genCtx) { + final Project project = + (Project) genCtx.getDataContext().getData(DataConstants.PROJECT); + + if (project != null) { + if ((paneTwoFile != null) && (paneTwoContents != null)) { + DiffFileToken paneOneToken = null; + + try { + paneOneToken = DiffFileToken.createForVirtualFile(paneTwoFile); + } + catch (IOException e) { + System.err.println(new StringBuffer("DiffFile plugin: could not read selected file: ").append( + paneTwoFile.getPath()).toString()); + e.printStackTrace(); + + Messages.showDialog(project, "Could not read contents of selected file.", // message + "Diff File Error", // title + new String[] { "Dismiss" }, 0, Messages.getErrorIcon()); + + return; + } + + if (paneOneToken != null) { + final DiffFileToken paneTwoToken = new DiffFileToken(); + + paneTwoToken.setName("Editor Contents"); + paneTwoToken.setTitle("Temporary Buffer"); + paneTwoToken.setContents(paneTwoContents); + paneTwoToken.setType(FileTypeManager.getInstance().getFileTypeByExtension(paneTwoFile.getExtension())); + + final DiffViewerFrame diffViewer = + new DiffViewerFrame(project /*, paneTwoFile */ , paneOneToken, paneTwoToken, genCtx); + + diffViewer.setVisible(true); + } + } + } + } +} diff --git a/src/org/intellij/plugins/testnggen/diff/DiffFileToken.java b/src/org/intellij/plugins/testnggen/diff/DiffFileToken.java new file mode 100644 index 0000000..fc498ea --- /dev/null +++ b/src/org/intellij/plugins/testnggen/diff/DiffFileToken.java @@ -0,0 +1,73 @@ +package org.intellij.plugins.testnggen.diff; + +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.vfs.VirtualFile; + +import java.io.IOException; + + +/** + * A basic Java bean that holds information about a file that is relevant for a diff viewer. + */ +public final class DiffFileToken { + private String _name; + private String _title; + private String _contents; + private FileType _type; + + public DiffFileToken() {} + + public DiffFileToken(String name, String title, String fileContents, FileType fileType) { + _name = name; + _title = title; + _contents = fileContents; + _type = fileType; + } + + /** + * Creates a token based upon the specified virtual file. The file's path is used for the name, + * the contents are extracted, and the file type is inferred from the file's extension. + * + * @param file The file the token will be based upon. + * @return A new DiffFileToken. + * @throws IOException If the contents of the virtual file can not be read. + */ + public static DiffFileToken createForVirtualFile(VirtualFile file) + throws IOException { + return new DiffFileToken(file.getName(), file.getPath(), String.valueOf(file.contentsToCharArray()), + FileTypeManager.getInstance().getFileTypeByExtension(file.getExtension())); + } + + public String getName() { + return _name; + } + + public void setName(String name) { + _name = name; + } + + public String getTitle() { + return _title; + } + + public void setTitle(String title) { + _title = title; + } + + public String getContents() { + return _contents; + } + + public void setContents(String contents) { + _contents = contents; + } + + public FileType getType() { + return _type; + } + + public void setType(FileType type) { + _type = type; + } +} diff --git a/src/org/intellij/plugins/testnggen/diff/DiffPanelHelper.java b/src/org/intellij/plugins/testnggen/diff/DiffPanelHelper.java new file mode 100644 index 0000000..72fda15 --- /dev/null +++ b/src/org/intellij/plugins/testnggen/diff/DiffPanelHelper.java @@ -0,0 +1,74 @@ +package org.intellij.plugins.testnggen.diff; + +import com.intellij.openapi.diff.DiffManager; +import com.intellij.openapi.diff.DiffPanel; +import com.intellij.openapi.diff.SimpleContent; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.project.Project; + +import java.awt.*; + + +/** + * Class to add some convenience abilities to the DiffPanel. + */ +public final class DiffPanelHelper { + private Project _project = null; + private DiffFileToken _paneTwoToken = null; + private DiffFileToken _paneOneToken = null; + private DiffPanel _panel = null; + private Window _window = null; + + /** + * Create a new DiffPanelHelper for the specified window, project, backing file, and contents. + * The virtual file is used when a line number is selected. + * + * @param window The window that will contain the diffPanel. + * @param project The project this window is associated with. + * @param paneOneToken A token containing information about the file to be placed in the left + * hand pane. + * @param paneTwoToken A token containing information about the file to be placed in the right + */ + public DiffPanelHelper(Window window, Project project, DiffFileToken paneOneToken, DiffFileToken paneTwoToken) { + _window = window; + _project = project; + _paneTwoToken = paneTwoToken; + _paneOneToken = paneOneToken; + } + + public String getTitle() { + return new StringBuffer(_paneOneToken.getName()). + append(" vs. ").append(_paneTwoToken.getName()) .toString(); + } + + public DiffPanel getDiffPanel() { + initDiffPanel(); + + return _panel; + } + + public void closeDiffPanel() { + if (_panel != null) { + _panel.dispose(); + _panel = null; + } + } + + private void initDiffPanel() { + if (_panel == null) { + _panel = DiffManager.getInstance().createDiffPanel(_window, _project); + + FileType fileType = _paneTwoToken.getType(); + + if (fileType == null) { + fileType = _paneOneToken.getType(); + } + + _panel.setTitle1(_paneOneToken.getTitle()); + _panel.setTitle2(_paneTwoToken.getTitle()); + _panel.setContents(new SimpleContent(_paneOneToken.getContents(), fileType), + new SimpleContent(_paneTwoToken.getContents(), fileType)); + } + } + +} diff --git a/src/org/intellij/plugins/testnggen/diff/DiffViewerFrame.java b/src/org/intellij/plugins/testnggen/diff/DiffViewerFrame.java new file mode 100644 index 0000000..9b0dcce --- /dev/null +++ b/src/org/intellij/plugins/testnggen/diff/DiffViewerFrame.java @@ -0,0 +1,149 @@ +package org.intellij.plugins.testnggen.diff; + +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.DimensionService; +import org.intellij.plugins.testnggen.FileCreator; +import org.intellij.plugins.testnggen.GeneratorContext; +import org.intellij.plugins.testnggen.util.GenUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.io.IOException; +import java.io.StringWriter; + + +public final class DiffViewerFrame extends JFrame implements DataProvider { + private static final String DIMENSION_KEY = "DiffViewer.JFrame"; + private Project _project = null; + private DiffPanelHelper _diffPanelHelper = null; + private final GeneratorContext _ctx; + private final String _content; + + public DiffViewerFrame(Project project /*, VirtualFile backingFile */, DiffFileToken paneOneToken, + DiffFileToken paneTwoToken, GeneratorContext ctx) { + setProject(project); + _diffPanelHelper = new DiffPanelHelper(this, project, paneOneToken, paneTwoToken); + + _ctx = ctx; + _content = paneTwoToken.getContents(); + setTitle(buildTitle()); + init(); + } + + public Project getProject() { + return _project; + } + + public void setProject(Project project) { + _project = project; + } + + public Object getData(String dataId) { + if (DataConstants.PROJECT.equals(dataId)) { + return _project; + } + else { + return null; + } + } + + public void dispose() { + _diffPanelHelper.closeDiffPanel(); + super.dispose(); + } + + private void init() { + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setIconImage(new ImageIcon(getClass().getResource("/diff/Diff.png")).getImage()); + + getRootPane().registerKeyboardAction(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dispose(); + } + }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); + + addWindowListener(new WindowAdapter() { + public void windowClosed(WindowEvent e) { + final DimensionService dimensionService = DimensionService.getInstance(); + dimensionService.setSize(DIMENSION_KEY, getSize()); + dimensionService.setLocation(DIMENSION_KEY, getLocation()); + } + }); + + final Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout(8, 0)); + contentPane.add(createCenterPanel(), BorderLayout.CENTER); + contentPane.add(createButtonPanel(), BorderLayout.SOUTH); + + pack(); + + final DimensionService dimensionService = DimensionService.getInstance(); + final Dimension size = dimensionService.getSize(DIMENSION_KEY); + + if (size != null) { + setSize(size); + } + + final Point location = dimensionService.getLocation(DIMENSION_KEY); + + if (location != null) { + setLocation(location); + } + else { + setLocationRelativeTo(null); + } + } + + JComponent createButtonPanel() { + final JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 8)); + final Action[] actions = createActions(); + + for (int index = 0; index < actions.length; index++) { + panel.add(new JButton(actions[index])); + } + + return panel; + } + + JComponent createCenterPanel() { + return _diffPanelHelper.getDiffPanel().getComponent(); + } + + Action[] createActions() { + final Action closeAction = + new AbstractAction("Close") { + public void actionPerformed(ActionEvent actionevent) { + DiffViewerFrame.this.setVisible(false); + DiffViewerFrame.this.dispose(); + } + }; + + final Action overwriteAction = + new AbstractAction("Overwrite") { + public void actionPerformed(ActionEvent actionevent) { + final StringWriter writer = new StringWriter(); + writer.write(_content); + + try { + ApplicationManager.getApplication().runWriteAction(new FileCreator(GenUtil.getOutputFile(_ctx, + _ctx.getOutputFileName()), writer, _ctx, true)); + DiffViewerFrame.this.setVisible(false); + DiffViewerFrame.this.dispose(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + }; + + return new Action[] { overwriteAction, closeAction }; + } + + private String buildTitle() { + return new StringBuffer("Diff: ").append(_diffPanelHelper.getTitle()).toString(); + } +} diff --git a/src/org/intellij/plugins/testnggen/ui/TestNGGenConfig.java b/src/org/intellij/plugins/testnggen/ui/TestNGGenConfig.java new file mode 100644 index 0000000..1a345da --- /dev/null +++ b/src/org/intellij/plugins/testnggen/ui/TestNGGenConfig.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) United Parcel Service of America, Inc. + * All Rights Reserved. + * + * The use, disclosure, reproduction, modification, transfer, or transmittal + * of this work for any purpose in any form or by any means without the + * written permission of United Parcel Service is strictly prohibited. + * Confidential, Unpublished Property of United Parcel Service. + * Use and Distribution Limited Solely to Authorized Personnel. + */ +package org.intellij.plugins.testnggen.ui; + +import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurationException; +import org.intellij.plugins.testnggen.Const; +import org.intellij.plugins.testnggen.util.GenUtil; + +import javax.swing.*; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * TestNGGenerator configuration UI. + * Could be accessed via File->Settings->(IDE Settings) TestNG Generator + * + * @author Alex Nazimok (SCI) + * @since
Sep 7, 2004+ */ +public class TestNGGenConfig implements ApplicationComponent, Configurable { + private Editor templateEditor; + private Editor propsEditor; + + private String templateContent = ""; + private String propsContent = ""; + + private static final String TEMPLATE_FILE = GenUtil.getResourcePath(Const.RELATIVE_DIR_NAME) + File.separator + Const.TEMPLATE_NAME; + private static final String PROPS_FILE = GenUtil.getResourcePath(Const.RELATIVE_DIR_NAME) + File.separator + Const.PROPERTIES_FILE_NAME; + + public final String getDisplayName() { + return "TestNG Generator"; + } + + public final Icon getIcon() { + return new ImageIcon(TestNGGenConfig.class.getResource("smalllogo.gif")); + } + + public final String getHelpTopic() { + return null; + } + + public final String getComponentName() { + return "TestNGGeneratorPlugin.TestNGGenConfig"; + } + + public final void initComponent() { + templateContent = readFile(TEMPLATE_FILE); + propsContent = readFile(PROPS_FILE); + } + + public final JComponent createComponent() { + final JTabbedPane tabbedPane = new JTabbedPane(); + + // test-case template configuration tab + final EditorFactory factory = EditorFactory.getInstance(); + final char[] chars = new char[templateContent.length()]; + templateContent.getChars(0, templateContent.length(), chars, 0); + + templateEditor = factory.createEditor(factory.createDocument(chars)); + tabbedPane.addTab("Velocity Template", templateEditor.getComponent()); + + templateEditor.getComponent().setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), TEMPLATE_FILE), + BorderFactory.createEmptyBorder(5, 5, 5, 5))); + + // Output Properties configuration tab + propsEditor = factory.createEditor(factory.createDocument(propsContent)); + tabbedPane.addTab("Output Pattern", propsEditor.getComponent()); + + propsEditor.getComponent().setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), PROPS_FILE), + BorderFactory.createEmptyBorder(5, 5, 5, 5))); + + return tabbedPane; + } + + public final boolean isModified() { + return !templateContent.equals(templateEditor.getDocument().getText()) || + !propsContent.equals(propsEditor.getDocument().getText()); + } + + public final void apply() throws ConfigurationException { + templateContent = templateEditor.getDocument().getText(); + propsContent = propsEditor.getDocument().getText(); + } + + private String readFile(String filename) { + RandomAccessFile file = null; + try { + file = new RandomAccessFile(filename, "r"); + final byte[] bytes = new byte[(int) file.length()]; + file.readFully(bytes); + return new String(bytes); + } + catch (Exception ex) { + GenUtil.getLogger(getClass().getName()).error(ex); + } + finally { + if (file != null) { + try { + file.close(); + } + catch (IOException ignore) { + ; // Do nothing + } + } + } + throw new RuntimeException("Unable to read config files."); + } + + private void writeFile(String filename, String content) { + FileWriter file = null; + try { + file = new FileWriter(new File(filename), false); + file.write(content); + } + catch (IOException e) { + GenUtil.getLogger(getClass().getName()).error(e); + } + finally { + if (file != null) { + try { + file.close(); + } + catch (IOException ignore) { + ; // Do nothing + } + } + } + + } + + public final void disposeUIResources() { + writeFile(TEMPLATE_FILE, templateContent); + writeFile(PROPS_FILE, propsContent); + } + + public final void disposeComponent() { + } + + public final void reset() { + } + +} diff --git a/src/org/intellij/plugins/testnggen/ui/smalllogo.gif b/src/org/intellij/plugins/testnggen/ui/smalllogo.gif new file mode 100644 index 0000000..af125b9 Binary files /dev/null and b/src/org/intellij/plugins/testnggen/ui/smalllogo.gif differ diff --git a/src/org/intellij/plugins/testnggen/util/GenUtil.java b/src/org/intellij/plugins/testnggen/util/GenUtil.java new file mode 100644 index 0000000..bc51c8a --- /dev/null +++ b/src/org/intellij/plugins/testnggen/util/GenUtil.java @@ -0,0 +1,177 @@ +package org.intellij.plugins.testnggen.util; + +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiJavaFile; +import org.intellij.plugins.testnggen.Const; +import org.intellij.plugins.testnggen.GeneratorContext; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Properties; +import java.util.Date; + + +/** + * General purpose utility class. + * + * @author Alex Nazimok (SCI) + * @since
Aug 30, 2003+ */ +public class GenUtil { + /** + * Disables the default constructor. + * + * @throws UnsupportedOperationException if the constructor is called. + */ + private GenUtil() throws UnsupportedOperationException { + throw new UnsupportedOperationException("Illegal constructor call."); + } + + /** + * Returns full path to the relativePath. + * + * @param relativePath directory relative to IDEA's home. + * @return Full path to the relativePath passed in. + */ + public static String getResourcePath(String relativePath) { + if (relativePath == null) { + throw new IllegalArgumentException("relative path should not be null"); + } + String pluginPath = PathManager.getPluginsPath(); + pluginPath = pluginPath + File.separator + relativePath; + + return pluginPath; + } + + /** + * Get's the javafile that's currently selected in the editor. Returns null if it's not a javafile. + * + * @param dataContext data context. + * @return The current javafile. Null if not a javafile. + */ + public static PsiJavaFile getSelectedJavaFile(DataContext dataContext) { + final PsiFile psiFile = (PsiFile) dataContext.getData("psi.File"); + + if (!(psiFile instanceof PsiJavaFile)) { + return null; + } + else { + return (PsiJavaFile) psiFile; + } + } + + /** + * Returns Project from DataContext + * + * @param ctx DataContext + * @return Project object + */ + public static Project getProject(DataContext ctx) { + return (Project) ctx.getData(DataConstants.PROJECT); + } + + /** + * Returns a logger + * + * @param className class name for which logger should be constructed + * @return a logger instance + */ + public static Logger getLogger(String className) { + return Logger.getInstance(className); + } + + /** + * Returns source paths for currently selected java file + * + * @param clss psiClass + * @return list of source paths + */ + public static String getSourcePath(PsiClass clss, DataContext ctx) { + + final VirtualFile[] roots = ProjectRootManager.getInstance(getProject(ctx)).getContentSourceRoots(); + final String className = clss.getContainingFile().getVirtualFile().getPath(); + + for (int i = 0; i < roots.length; i++) { + if (className.startsWith(roots[i].getPath())) { + return roots[i].getPath(); + } + } + + return null; + } + + /** + * Returns an output pattern + * + * @return output pattern + * @throws java.io.IOException + */ + public static String getOutputPattern(GeneratorContext genCtx) + throws IOException { + final String resourcePath = getResourcePath(Const.RELATIVE_DIR_NAME); + final Properties configProps = new Properties(); + configProps.load(new FileInputStream(resourcePath + '/' + Const.PROPERTIES_FILE_NAME)); + String outputPattern = configProps.getProperty(getProject(genCtx.getDataContext()).getName()); + + if (outputPattern == null || outputPattern.trim().length() == 0) { + outputPattern = configProps + .getProperty(Const.OUTPUT_KEY); + } + + return outputPattern; + } + + /** + * Returns absolute path + filename of the output file + * + * @param genCtx GeneratorContext + * @return absolute path + filename of the output file + * @throws java.io.IOException + */ + public static String getOutputFile(GeneratorContext genCtx, String testClassName) + throws IOException { + String outputPattern = getOutputPattern(genCtx); + String sourcePath = getSourcePath(genCtx.getPsiClass(), genCtx.getDataContext()); + + if (sourcePath == null) { + throw new IllegalArgumentException("Sourcepath cannot be null"); + } + + final String packageName = genCtx.getFile().getPackageName(); + + final int indexOf = sourcePath.indexOf("$SOURCEPATH$"); + + if (indexOf != -1) { + sourcePath = sourcePath.substring(indexOf); + } + + outputPattern = StringUtil.replace(outputPattern, "$SOURCEPATH$", sourcePath); + outputPattern = StringUtil.replace(outputPattern, "$PACKAGE$", packageName.replace('.', '/')); + outputPattern = StringUtil.replace(outputPattern, "$FILENAME$", testClassName); + + return outputPattern; + } + + /** + * Returns Current date as formatted string, format specified by pattern argument. + * + * @param pattern date format + * @return current date as formatted string, format specified by pattern argument. + * @see SimpleDateFormat + */ + public static String formatDate(String pattern) { + final SimpleDateFormat sdf = new SimpleDateFormat(pattern); + + return sdf.format(new Date()); + } +} diff --git a/src/org/intellij/plugins/testnggen/util/StringUtil.java b/src/org/intellij/plugins/testnggen/util/StringUtil.java new file mode 100644 index 0000000..e60b9e1 --- /dev/null +++ b/src/org/intellij/plugins/testnggen/util/StringUtil.java @@ -0,0 +1,76 @@ +package org.intellij.plugins.testnggen.util; + + +/** + * + * @author Alex Nazimok (SCI) + * @since
Aug 30, 2003+ */ +public class StringUtil { + /** + * Disables the default constructor. + * + * @throws UnsupportedOperationException if the constructor is called. + */ + private StringUtil() throws UnsupportedOperationException { + throw new UnsupportedOperationException("Illegal constructor call."); + } + + /** + * Replaces all occurrences of
replPattern
in the inputStr
+ * with replaceWith
string.
+ * @param inputStr input string
+ * @param replPattern replace pattern
+ * @param replaceWith string to replace replPattern
+ * @return inputStr with all occurrences of replPattern being replaced with relaceWith string.
+ */
+ public static String replace(String inputStr, String replPattern, String replaceWith) {
+ while (true) {
+ final int indexOf = inputStr.indexOf(replPattern);
+
+ if (indexOf == -1) {
+ break;
+ }
+
+ final int end = indexOf + replPattern.length();
+
+ inputStr = inputStr.substring(0, indexOf) + replaceWith + inputStr.substring(end);
+ }
+
+ return inputStr;
+ }
+
+ /**
+ * Capitalizes string passed in
+ * @param strIn string to be capitalized
+ * @return capitalized string
+ * @throws java.lang.IndexOutOfBoundsException
+ */
+ public static String cap(String strIn) throws IndexOutOfBoundsException {
+ if ((strIn == null) || (strIn.trim().length() == 0)) {
+ throw new IllegalArgumentException("Argumnet strIn in method GenUtil.cap must not be null.");
+ }
+
+ return String.valueOf(strIn.charAt(0)).toUpperCase() + strIn.substring(1);
+ }
+
+ /**
+ * Removes package name from classname
+ * @param className class name
+ * @return class name without package name
+ */
+ public static String trimPackageName(String className) {
+ if (className == null) {
+ return null;
+ }
+
+ final int indexOf = className.lastIndexOf('.');
+
+ if (indexOf != -1) {
+ return className.substring(indexOf + 1);
+ }
+ else {
+ return className;
+ }
+ }
+}
diff --git a/testnggen.iml b/testnggen.iml
new file mode 100644
index 0000000..42f4a19
--- /dev/null
+++ b/testnggen.iml
@@ -0,0 +1,42 @@
+
+