blob: 711e54dda863a71e3ef7b8d4e185a48c42b9dd58 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.beans.beaninfo;
import java.awt.Dialog;
import java.awt.EventQueue;
import java.util.concurrent.Future;
import javax.lang.model.element.TypeElement;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.modules.beans.PatternAnalyser;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.RequestProcessor.Task;
import org.openide.util.TaskListener;
import org.openide.util.actions.NodeAction;
/**
* Generate BI action.
*
* @author Petr Hrebejk
*/
@ActionID(id="org.netbeans.modules.beans.beaninfo.GenerateBeanInfoAction", category="Tools")
@ActionRegistration(lazy=false, displayName="#CTL_GENBI_MenuItem")
@ActionReference(path="Loaders/text/x-java/Actions", position=2120, separatorAfter=2140)
public final class GenerateBeanInfoAction extends NodeAction implements java.awt.event.ActionListener {
private Dialog biDialog;
/** generated Serialized Version UID */
//static final long serialVersionUID = 1391479985940417455L;
// The dialog for BeanInfo generation
static final long serialVersionUID =-4937492476805017833L;
/** Human presentable name of the action. This should be
* presented as an item in a menu.
* @return the name of the action
*/
public String getName () {
return getString ("CTL_GENBI_MenuItem");
}
/** The action's icon location.
* @return the action's icon location
*/
@Override
protected String iconResource () {
return null;
//return "/org/netbeans/modules/javadoc/resources/searchDoc.gif"; // NOI18N
}
/** Help context where to find more about the action.
* @return the help context for this action
*/
public HelpCtx getHelpCtx () {
return HelpCtx.DEFAULT_HELP;
}
protected boolean enable( Node[] activatedNodes ) {
if (activatedNodes.length != 1) {
return false;
} else {
FileObject fo = findFileObject(activatedNodes[0]);
return fo != null && JavaSource.forFileObject(fo) != null
&& !fo.getName().endsWith("BeanInfo"); //NOI18N
}
}
/** This method is called by one of the "invokers" as a result of
* some user's action that should lead to actual "performing" of the action.
* This default implementation calls the assigned actionPerformer if it
* is not null otherwise the action is ignored.
*/
public void performAction ( final Node[] nodes ) {
if (nodes.length != 1)
return;
// Open the diaog for bean info generation
final BiPanel biPanel = new BiPanel();
// Get pattern analyser & bean info and create BiAnalyser & BiNode
FileObject javaFile = findFileObject(nodes[0]);
final BeanInfoWorker performer = new BeanInfoWorker(javaFile, biPanel);
class Task implements TaskListener, Runnable {
public void taskFinished(org.openide.util.Task task) {
EventQueue.invokeLater(this);
}
public void run() {
if (performer.error != null) {
DialogDisplayer.getDefault().notify(performer.error);
}
if (performer.bia != null) {
performer.bia.openSource();
}
}
}
performer.analyzePatterns().addTaskListener(new Task());
}
@Override
protected boolean asynchronous() {
return false;
}
private void initAccessibility() {
biDialog.getAccessibleContext().setAccessibleDescription(getString("ACSD_BeanInfoEditorDialog"));
}
private static FileObject findFileObject(Node n) {
DataObject dobj = n.getCookie(DataObject.class);
return dobj != null? dobj.getPrimaryFile() : null;
}
static String getString(String key) {
return NbBundle.getBundle("org.netbeans.modules.beans.beaninfo.Bundle").getString(key);
}
static final class BeanInfoWorker implements Runnable, org.netbeans.api.java.source.Task<CompilationController> {
private final BiPanel biPanel;
private final FileObject javaFile;
private boolean isCancelled = false;
private Node biNode;
private BiAnalyser bia;
private Task task;
private int state = 0;
private NotifyDescriptor error;
public BeanInfoWorker(FileObject javaFile, BiPanel biPanel) {
this.javaFile = javaFile;
this.biPanel = biPanel;
}
public Task analyzePatterns() {
checkState(0);
task = RequestProcessor.getDefault().post(this);
return task;
}
public void updateUI() {
waitFinished();
checkState(1);
state = 2;
// fillBiPanel();
EventQueue.invokeLater(this);
}
public void generateSources() {
waitFinished();
checkState(2);
state = 3;
// task.schedule(0);
try {
run();
} finally {
state = 2;
}
}
public boolean isCancelled() {
return isCancelled;
}
public void waitFinished() {
if (task == null) {
throw new IllegalStateException();
}
task.waitFinished();
}
public boolean isModelModified() {
waitFinished();
return bia != null? bia.isModified(): false;
}
public void run() {
if (isCancelled) {
return;
}
switch(state) {
case 0:
analyzePatternsImpl();
break;
case 2:
fillBiPanel();
break;
case 3:
generateSourcesImpl();
break;
}
}
public void run(CompilationController javac) throws Exception {
if (isCancelled) {
return;
}
javac.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
switch(state) {
case 1:
analyzePatternsImpl(javac);
break;
}
}
private void analyzePatternsImpl(CompilationInfo javac) {
checkState(1);
String clsname = javaFile.getName();
TypeElement clselm = null;
for (TypeElement top : javac.getTopLevelElements()) {
if (clsname.contentEquals(top.getSimpleName())) {
clselm = top;
}
}
if (clselm == null) {
isCancelled = true;
error = new NotifyDescriptor.Message(
NbBundle.getMessage(
GenerateBeanInfoAction.class,
"MSG_FileWitoutTopLevelClass",
clsname, FileUtil.getFileDisplayName(javaFile)
),
NotifyDescriptor.ERROR_MESSAGE);
return;
}
PatternAnalyser pa = new PatternAnalyser(javaFile, null, true);
pa.analyzeAll(javac, clselm);
// XXX analyze also superclasses here
try {
bia = new BiAnalyser(pa, javac);
} catch (Exception ex) {
isCancelled = true;
Exceptions.printStackTrace(ex);
}
}
private void analyzePatternsImpl() {
if (javaFile == null) {
isCancelled = true;
return;
}
checkState(0);
state = 1;
try {
JavaSource.forFileObject(javaFile).runUserActionTask(this, true);
} catch (Exception ex) {
isCancelled = true;
Exceptions.printStackTrace(ex);
}
}
private void fillBiPanel() {
biNode = BiNode.createBiNode(bia, error);
biPanel.setContext( biNode );
biPanel.expandAll();
}
private void generateSourcesImpl() {
if (!isCancelled() && bia != null && !bia.isBeanBroken()) {
bia.regenerateSource();
}
}
private void checkState(int expected) {
if (state != expected) {
throw new IllegalStateException();
}
}
}
}