/*
 * 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.maven.jaxws.wizards;

import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.VariableTree;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.swing.SwingUtilities;

import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.source.CancellableTask;
import org.netbeans.api.java.source.Comment;
import org.netbeans.api.java.source.GeneratorUtilities;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.ui.ScanDialog;
import org.netbeans.api.java.source.ModificationResult;
import org.netbeans.api.java.source.TreeMaker;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.netbeans.modules.j2ee.api.ejbjar.EjbReference;
import org.netbeans.modules.j2ee.core.api.support.classpath.ContainerClassPathModifier;
import org.netbeans.modules.maven.jaxws.MavenJAXWSSupportImpl;
import org.netbeans.modules.maven.jaxws.MavenWebService;
import org.netbeans.modules.maven.jaxws.WSUtils;
import org.netbeans.modules.maven.model.ModelOperation;
import org.netbeans.modules.maven.model.Utilities;
import org.netbeans.modules.maven.model.pom.POMModel;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModeler;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlOperation;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlParameter;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlPort;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlService;
import org.netbeans.modules.websvc.api.support.ServiceCreator;
import java.io.IOException;
import org.netbeans.api.java.project.JavaProjectConstants;

import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;

import org.netbeans.modules.maven.api.execute.RunConfig;
import org.netbeans.modules.maven.api.execute.RunUtils;
import org.netbeans.modules.maven.jaxws.MavenModelUtils;
import org.netbeans.modules.websvc.api.support.java.GenerationUtils;
import org.netbeans.modules.websvc.api.support.java.SourceUtils;
import org.netbeans.modules.websvc.jaxws.light.api.JAXWSLightSupport;
import org.netbeans.spi.project.ui.templates.support.Templates;
import org.openide.DialogDisplayer;
import org.openide.ErrorManager;
import org.openide.NotifyDescriptor;
import org.openide.WizardDescriptor;
import org.openide.cookies.OpenCookie;
import org.openide.cookies.SaveCookie;
import org.openide.execution.ExecutorTask;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;

/**
 *
 * @author Radko, Milan Kuchtiak
 */
public class JaxWsServiceCreator implements ServiceCreator {
    private static final String SOAP_BINDING_TYPE = "javax.xml.ws.soap.SOAPBinding";  //NOI18N
    private static final String BINDING_TYPE_ANNOTATION = "javax.xml.ws.BindingType"; //NOI18N
    private static final String SOAP12_HTTP_BINDING = "SOAP12HTTP_BINDING"; //NOI18N
    
    private Project project;
    private WizardDescriptor wiz;
    private boolean addJaxWsLib;
    private int serviceType;
    
    private static final Logger LOG = Logger.getLogger( JaxWsServiceCreator.class.getCanonicalName());

    /**
     * Creates a new instance of WebServiceClientCreator
     */
    public JaxWsServiceCreator(Project project, WizardDescriptor wiz, boolean addJaxWsLib) {
        this.project = project;
        this.wiz = wiz;
        this.addJaxWsLib = addJaxWsLib;
    }

    @Override
    public void createService() throws IOException {
        serviceType = ((Integer) wiz.getProperty(WizardProperties.WEB_SERVICE_TYPE)).intValue();

        // Use Progress API to display generator messages.
        final ProgressHandle handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(JaxWsServiceCreator.class, "TXT_WebServiceGeneration")); //NOI18N
        handle.start(100);

        Runnable r = new Runnable() {

            @Override
            public void run() {
                try {
                    generateWebService(handle);
                } catch (IOException e) {
                    //finish progress bar
                    handle.finish();
                    String message = e.getLocalizedMessage();
                    if (message != null) {
                        ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
                        NotifyDescriptor nd = new NotifyDescriptor.Message(message, NotifyDescriptor.ERROR_MESSAGE);
                        DialogDisplayer.getDefault().notify(nd);
                    } else {
                        ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, e);
                    }
                }
            }
        };
        RequestProcessor.getDefault().post(r);
    }

    @Override
    public void createServiceFromWsdl() throws IOException {

        //initProjectInfo(project);

        final ProgressHandle handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(JaxWsServiceCreator.class, "TXT_WebServiceGeneration")); //NOI18N

        Runnable r = new Runnable() {

            @Override
            public void run() {
                try {
                    handle.start(100);
                    generateWsFromWsdl15(handle);
                } catch (IOException e) {
                    //finish progress bar
                    handle.finish();
                    String message = e.getLocalizedMessage();
                    if (message != null) {
                        ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
                        NotifyDescriptor nd = new NotifyDescriptor.Message(message, NotifyDescriptor.ERROR_MESSAGE);
                        DialogDisplayer.getDefault().notify(nd);
                    } else {
                        ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, e);
                    }
                }
            }
        };
        RequestProcessor.getDefault().post(r);
    }

    //TODO it should be refactored to prevent duplicate code but it is more readable now during development
    private void generateWebService(ProgressHandle handle) throws IOException {

        FileObject pkg = Templates.getTargetFolder(wiz);

        if (serviceType == WizardProperties.FROM_SCRATCH) {
            handle.progress(NbBundle.getMessage(JaxWsServiceCreator.class, "MSG_GEN_WS"), 50); //NOI18N
            //add the JAXWS 2.0 library, if not already added
            if (addJaxWsLib) {
                MavenModelUtils.addMetroLibrary(project);
            }
            generateJaxWSImplFromTemplate(pkg, WSUtils.isEJB(project), false, false);
            handle.finish();
        } else if (serviceType == WizardProperties.ENCAPSULATE_SESSION_BEAN) {
            String wsName = Templates.getTargetName(wiz);
            handle.progress(NbBundle.getMessage(JaxWsServiceCreator.class, "MSG_GEN_SEI_AND_IMPL"), 50); //NOI18N
            Node[] nodes = (Node[]) wiz.getProperty(WizardProperties.DELEGATE_TO_SESSION_BEAN);
            generateWebServiceFromEJB(wsName, pkg, nodes);
            handle.finish();
        }
    }

    private void generateWsFromWsdl15(final ProgressHandle handle) throws IOException {
        handle.progress(NbBundle.getMessage(JaxWsServiceCreator.class, "MSG_GEN_WS"), 50); //NOI18N

        JAXWSLightSupport jaxWsSupport = JAXWSLightSupport.getJAXWSLightSupport(project.getProjectDirectory());
        String wsdlUrl = (String)wiz.getProperty(WizardProperties.WSDL_URL);
        String filePath = (String)wiz.getProperty(WizardProperties.WSDL_FILE_PATH);

        //Boolean useDispatch = (Boolean) wiz.getProperty(ClientWizardProperties.USEDISPATCH);
        //if (wsdlUrl==null) wsdlUrl = "file:"+(filePath.startsWith("/")?filePath:"/"+filePath); //NOI18N

        if(wsdlUrl == null) {
            wsdlUrl = FileUtil.toFileObject(FileUtil.normalizeFile(new File(filePath))).getURL().toExternalForm();
        }
        FileObject localWsdlFolder = jaxWsSupport.getWsdlFolder(true);

        boolean hasSrcFolder = false;
        File srcFile = new File (FileUtil.toFile(project.getProjectDirectory()),"src"); //NOI18N
        if (srcFile.exists()) {
            hasSrcFolder = true;
        } else {
            hasSrcFolder = srcFile.mkdirs();
        }

        if (localWsdlFolder != null) {
            FileObject wsdlFo = null;
            try {
                wsdlFo = WSUtils.retrieveResource(
                        localWsdlFolder,
                        (hasSrcFolder ? new URI(MavenJAXWSSupportImpl.CATALOG_PATH) : new URI("jax-ws-catalog.xml")), //NOI18N
                        new URI(wsdlUrl));
            } catch (URISyntaxException ex) {
                //ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
                String mes = NbBundle.getMessage(JaxWsServiceCreator.class, "ERR_IncorrectURI", wsdlUrl); // NOI18N
                NotifyDescriptor desc = new NotifyDescriptor.Message(mes, NotifyDescriptor.Message.ERROR_MESSAGE);
                DialogDisplayer.getDefault().notify(desc);
            } catch (UnknownHostException ex) {
                //ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
                String mes = NbBundle.getMessage(JaxWsServiceCreator.class, "ERR_UnknownHost", ex.getMessage()); // NOI18N
                NotifyDescriptor desc = new NotifyDescriptor.Message(mes, NotifyDescriptor.Message.ERROR_MESSAGE);
                DialogDisplayer.getDefault().notify(desc);
            } catch (IOException ex) {
                //ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
                String mes = NbBundle.getMessage(JaxWsServiceCreator.class, "ERR_WsdlRetrieverFailure", wsdlUrl); // NOI18N
                NotifyDescriptor desc = new NotifyDescriptor.Message(mes, NotifyDescriptor.Message.ERROR_MESSAGE);
                DialogDisplayer.getDefault().notify(desc);
            }

            if (wsdlFo != null) {
                final WsdlService wsdlService = (WsdlService) wiz.getProperty(WizardProperties.WSDL_SERVICE);
                final WsdlPort wsdlPort = (WsdlPort) wiz.getProperty(WizardProperties.WSDL_PORT);

                if (wsdlService == null || wsdlPort == null) {
                    WsdlModeler wsdlModeler = (WsdlModeler) wiz.getProperty(WizardProperties.WSDL_MODELER);
                    if (wsdlModeler != null && wsdlModeler.getCreationException() != null) {
                        handle.finish();
                        DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(
                                NbBundle.getMessage(JaxWsServiceCreator.class, "TXT_CannotGenerateArtifacts",
                                wsdlModeler.getCreationException().getLocalizedMessage()),
                                NotifyDescriptor.ERROR_MESSAGE));
                    } else {
                        handle.finish();
                    }
                } else {
                    final boolean isJaxWsLibrary = MavenModelUtils.hasJaxWsAPI(project);
                    final String relativePath = FileUtil.getRelativePath(localWsdlFolder, wsdlFo);
                    final String serviceName = wsdlFo.getName();

                    Preferences prefs = ProjectUtils.getPreferences(project, MavenWebService.class,true);
                    if (prefs != null) {
                        // remember original WSDL URL for service
                        prefs.put(MavenWebService.SERVICE_PREFIX+WSUtils.getUniqueId(wsdlFo.getName(), jaxWsSupport.getServices()), wsdlUrl);
                    }

                    if (!isJaxWsLibrary) {
                        try {
                            MavenModelUtils.addMetroLibrary(project);
                            MavenModelUtils.addJavadoc(project);
                        } catch (Exception ex) {
                            Logger.getLogger(
                                JaxWsServiceCreator.class.getName()).log(
                                    Level.INFO, "Cannot add Metro libbrary to pom file", ex); //NOI18N
                        }
                    }

                    ModelOperation<POMModel> operation = new ModelOperation<POMModel>() {
                        @Override
                        public void performOperation(POMModel model) {
                            org.netbeans.modules.maven.model.pom.Plugin plugin =
                                    WSUtils.isEJB(project) ?
                                        MavenModelUtils.addJaxWSPlugin(model, "2.0") : //NOI18N
                                        MavenModelUtils.addJaxWSPlugin(model);
                            MavenModelUtils.addWsimportExecution(plugin, 
                                    serviceName, relativePath,null );
                            if (WSUtils.isWeb(project)) { // expecting web project
                                MavenModelUtils.addWarPlugin(model, false);
                            } else { // J2SE Project
                                MavenModelUtils.addWsdlResources(model);
                            }
                        }
                    };
                    Utilities.performPOMModelOperations(project.getProjectDirectory().getFileObject("pom.xml"),
                            Collections.singletonList(operation));

                    // create empty web service implementation class
                    FileObject pkg = Templates.getTargetFolder(wiz);
                    boolean useProvider = (Boolean)wiz.getProperty(WizardProperties.USE_PROVIDER);
                    boolean isStateless = (Boolean)wiz.getProperty(WizardProperties.IS_STATELESS_BEAN);
                    
                    final FileObject targetFile = generateJaxWSImplFromTemplate(pkg, isStateless, true, useProvider);

                    // execute wsimport goal
                    RunConfig cfg = RunUtils.createRunConfig(
                            FileUtil.toFile(project.getProjectDirectory()),
                            project,
                            "JAX-WS:wsimport", //NOI18N
                            Collections.singletonList("compile")); //NOI18N
                    ExecutorTask task = RunUtils.executeMaven(cfg);
                    try {
                        task.waitFinished(60000);
                    } catch (InterruptedException ex) {

                    }

                    try {
                        String wsdlLocationPrefix = WSUtils.isWeb(project) ? "WEB-INF/wsdl/" : "META-INF/wsdl/"; //NOI18N
                        generateJaxWsImplClass(targetFile, wsdlService, wsdlPort, wsdlLocationPrefix+relativePath, useProvider); //NOI18N
                        DataObject targetDo = DataObject.find(targetFile);
                        if (targetDo != null) {
                            SaveCookie save = targetDo.getCookie(SaveCookie.class);
                            if (save != null) {
                                save.save();
                            }
                        }

                    } catch (IOException ex) {
                        ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, ex);
                    }
                }

            }
        }

        handle.finish();
    }
    
    private FileObject generateJaxWSImplFromTemplate(FileObject pkg, boolean isEjbTemplate, boolean fromWsdl, boolean useProvider) throws IOException {
        DataFolder df = DataFolder.findFolder(pkg);
        FileObject template = Templates.getTemplate(wiz);

        if (useProvider) {
            FileObject templateParent = template.getParent();
            if (isEjbTemplate) {
                template = templateParent.getFileObject("EjbWebServiceProvider", "java"); //NOI18N
            } else {
                template = templateParent.getFileObject("WebServiceProvider", "java"); //NOI18N
            }
        } else if (!fromWsdl && (Boolean)wiz.getProperty(WizardProperties.IS_STATELESS_BEAN)) {
            FileObject templateParent = template.getParent();
            template = templateParent.getFileObject("EjbWebService", "java"); //NOI18N
        }
        
        DataObject dTemplate = DataObject.find(template);

        DataObject dobj = dTemplate.createFromTemplate(df, Templates.getTargetName(wiz));
        FileObject createdFile = dobj.getPrimaryFile();
        /*createdFile.setAttribute("jax-ws-service", java.lang.Boolean.TRUE);     // NOI18N
        try {
            dobj.setValid(false);
        }
        catch( PropertyVetoException e ){
            LOG.log(Level.WARNING, null , e);
        }*/
        dobj = DataObject.find(createdFile);
        
           
        openFileInEditor(dobj);

        return createdFile;
    }
    
    private ClassPath getClassPathForFile(Project project, FileObject file) {
        SourceGroup[] srcGroups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
        for (SourceGroup srcGroup: srcGroups) {
            FileObject srcRoot = srcGroup.getRootFolder();
            if (FileUtil.isParentOf(srcRoot, file)) {
                return ClassPath.getClassPath(srcRoot, ClassPath.SOURCE);
            }
        }
        return null;
    }
    
    public static void openFileInEditor(DataObject dobj) {

        final OpenCookie openCookie = dobj.getCookie(OpenCookie.class);
        if (openCookie != null) {
            RequestProcessor.getDefault().post(new Runnable() {

                @Override
                public void run() {
                    openCookie.open();
                }
            }, 1000);
        }
    }

    private void generateJaxWsImplClass(FileObject targetFile, final WsdlService service, final WsdlPort port, final String wsdlLocation, final boolean useProvider) throws IOException {

        final JavaSource targetSource = JavaSource.forFileObject(targetFile);
        final boolean[] isIncomplete = new boolean[1];
        final CancellableTask<WorkingCopy> task = new CancellableTask<WorkingCopy>() {

            @Override
            public void run(WorkingCopy workingCopy) throws java.io.IOException {
                workingCopy.toPhase(Phase.RESOLVED);
                ClassTree javaClass = SourceUtils.getPublicTopLevelTree(workingCopy);
                if (javaClass != null) {
                    TreeMaker make = workingCopy.getTreeMaker();
                    GenerationUtils genUtils = GenerationUtils.newInstance(workingCopy);

                    //add @WebService annotation
                    List<ExpressionTree> attrs = new ArrayList<ExpressionTree>();
                    attrs.add(
                            make.Assignment(make.Identifier("serviceName"), 
                                    make.Literal(service.getName()))); //NOI18N
                    attrs.add(
                            make.Assignment(make.Identifier("portName"), 
                                    make.Literal(port.getName()))); //NOI18N
                    
                    if (!useProvider) {
                        attrs.add(
                            make.Assignment(make.Identifier("endpointInterface"), 
                                    make.Literal(port.getJavaName()))); //NOI18N
                    }
                    attrs.add(
                            make.Assignment(make.Identifier("targetNamespace"), 
                                    make.Literal(port.getNamespaceURI()))); //NOI18N
                    attrs.add(
                            make.Assignment(make.Identifier("wsdlLocation"), 
                                    make.Literal(wsdlLocation))); //NOI18N

                    AnnotationTree WSAnnotation = make.Annotation(
                            useProvider ? 
                                make.QualIdent("javax.xml.ws.WebServiceProvider") : make.QualIdent("javax.jws.WebService"),      //NOI18N
                            attrs);
                    ClassTree  modifiedClass = genUtils.addAnnotation(javaClass, 
                            WSAnnotation);

                    if (WsdlPort.SOAP_VERSION_12.equals(port.getSOAPVersion())) {
                        //if SOAP 1.2 binding, add BindingType annotation
                        TypeElement bindingElement = workingCopy.getElements().
                            getTypeElement(BINDING_TYPE_ANNOTATION);
                        if (bindingElement == null) {
                            isIncomplete[0] = true;
                        }
                        else {
                            TypeElement soapBindingElement = workingCopy.
                                getElements().getTypeElement(SOAP_BINDING_TYPE);
                            ExpressionTree exp = make.MemberSelect(
                                    make.QualIdent(soapBindingElement), SOAP12_HTTP_BINDING);

                            AnnotationTree bindingAnnotation = make.Annotation(
                                    make.QualIdent(bindingElement),
                                    Collections.<ExpressionTree>singletonList(exp));

                            modifiedClass = genUtils.addAnnotation(modifiedClass, 
                                    bindingAnnotation);
                        }
                    }

                    if (!useProvider) {
                        // add @Stateless annotation
                        if (WSUtils.isEJB(project)) {
                            TypeElement statelessAn = workingCopy.getElements().
                                getTypeElement("javax.ejb.Stateless"); //NOI18N
                            if (statelessAn != null) {
                                AnnotationTree StatelessAnnotation = make.Annotation(
                                        make.QualIdent(statelessAn),
                                        Collections.<ExpressionTree>emptyList());
                                modifiedClass = genUtils.addAnnotation(modifiedClass, 
                                        StatelessAnnotation);
                            }
                            else {
                                isIncomplete[0] = true;
                            }
                        }

                        List<WsdlOperation> operations = port.getOperations();
                        for (WsdlOperation operation : operations) {

                            // return type
                            String returnType = operation.getReturnTypeName();

                            // create parameters
                            List<WsdlParameter> parameters = operation.getParameters();
                            List<VariableTree> params = new ArrayList<VariableTree>();
                            for (WsdlParameter parameter : parameters) {
                                // create parameter:
                                // final ObjectOutput arg0
                                params.add(make.Variable(
                                        make.Modifiers(
                                        Collections.<Modifier>emptySet(),
                                        Collections.<AnnotationTree>emptyList()),
                                        parameter.getName(), // name
                                        make.Identifier(parameter.getTypeName()), // parameter type
                                        null // initializer - does not make sense in parameters.
                                        ));
                            }

                            // create exceptions
                            Iterator<String> exceptions = operation.getExceptions();
                            List<ExpressionTree> exc = new ArrayList<ExpressionTree>();
                            while (exceptions.hasNext()) {
                                String exception = exceptions.next();
                                TypeElement excEl = workingCopy.getElements().getTypeElement(exception);
                                if (excEl != null) {
                                    exc.add(make.QualIdent(excEl));
                                } else {
                                    isIncomplete[0] = true;
                                    exc.add(make.Identifier(exception));
                                }
                            }

                            // create method
                            ModifiersTree methodModifiers = make.Modifiers(
                                    Collections.<Modifier>singleton(Modifier.PUBLIC),
                                    Collections.<AnnotationTree>emptyList());
                            MethodTree method = make.Method(
                                    methodModifiers, // public
                                    operation.getJavaName(), // operation name
                                    make.Identifier(returnType), // return type
                                    Collections.<TypeParameterTree>emptyList(), // type parameters - none
                                    params,
                                    exc, // throws
                                    "{ //TODO implement this method\nthrow new UnsupportedOperationException(\"Not implemented yet.\") }", // body text
                                    null // default value - not applicable here, used by annotations
                                    );

                            modifiedClass = make.addClassMember(modifiedClass, method);
                        }
                    }
                    workingCopy.rewrite(javaClass, modifiedClass);

                }
            }
            @Override
            public void cancel() {
            }
        };
        ModificationResult modificationTask = targetSource.runModificationTask(task);
        if ( isIncomplete[0] && 
                org.netbeans.api.java.source.SourceUtils.isScanInProgress())
        {
            final String title = NbBundle.getMessage(JaxWsServiceCreator.class, 
                    "LBL_GenWsClass");      // NOI18N
            final Runnable runnable = new Runnable() {
                
                @Override
                public void run() {
                    try {
                        targetSource.runModificationTask(task).commit();
                    }
                    catch ( IOException e){
                        Logger.getLogger( JaxWsServiceCreator.class.getCanonicalName()).
                            log(Level.WARNING , null , e);
                    }
                }
            };
            if ( SwingUtilities.isEventDispatchThread() ){
                ScanDialog.runWhenScanFinished(runnable, title);
            }
            else {
                SwingUtilities.invokeLater( new Runnable() {
                    
                    @Override
                    public void run() {
                        ScanDialog.runWhenScanFinished(runnable, title);
                    }
                });
            }
        }
        else {
            modificationTask.commit();
        }
    }

    private void generateWebServiceFromEJB(String wsName, FileObject pkg, Node[] nodes) throws IOException {

        if (nodes != null && nodes.length == 1) {

            EjbReference ejbRef = nodes[0].getLookup().lookup(EjbReference.class);
            if (ejbRef != null) {

                DataFolder df = DataFolder.findFolder(pkg);
                FileObject template = Templates.getTemplate(wiz);
                FileObject templateParent = template.getParent();
                if ((Boolean)wiz.getProperty(WizardProperties.IS_STATELESS_BEAN)) {
                    template = templateParent.getFileObject("EjbWebServiceNoOp", "java"); //NOI18N
                } else {
                    template = templateParent.getFileObject("WebServiceNoOp", "java"); //NOI18N
                }
                DataObject dTemplate = DataObject.find(template);
                DataObject dobj = dTemplate.createFromTemplate(df, wsName);
                FileObject createdFile = dobj.getPrimaryFile();
                /*createdFile.setAttribute("jax-ws-service", java.lang.Boolean.TRUE); // NOI18N
                try {
                    dobj.setValid(false);
                }
                catch( PropertyVetoException e ){
                    LOG.log(Level.WARNING, null , e);
                }*/
                dobj = DataObject.find(createdFile);
                

                ClassPath classPath = getClassPathForFile(project, createdFile);
                if (classPath != null) {
                    if (classPath.findResource("javax/ejb/EJB.class") == null) { //NOI19\8N
                        // ad EJB API on classpath
                        ContainerClassPathModifier modifier = project.getLookup().lookup(ContainerClassPathModifier.class);
                        if (modifier != null) {
                            modifier.extendClasspath(createdFile, new String[] {
                                ContainerClassPathModifier.API_EJB
                            });
                        }
                    }
                    generateDelegateMethods(createdFile, ejbRef);
                    openFileInEditor(dobj);
                }
            }
        }
    }
    private void generateDelegateMethods(final FileObject targetFo, final EjbReference ref) throws IOException {
        final boolean[] onClassPath = new boolean[1];
        final String[] interfaceClass = new String[1];

        final JavaSource targetSource = JavaSource.forFileObject(targetFo);
        final CancellableTask<WorkingCopy> modificationTask = new CancellableTask<WorkingCopy>() {

            @Override
            public void run(WorkingCopy workingCopy) throws IOException {
                workingCopy.toPhase(Phase.RESOLVED);

                TreeMaker make = workingCopy.getTreeMaker();

                TypeElement typeElement = SourceUtils.getPublicTopLevelElement(workingCopy);
                if (typeElement != null) {
                    VariableTree ejbRefInjection = null;
                    interfaceClass[0] = ref.getLocal();
                    if (interfaceClass[0] == null) {
                        interfaceClass[0] = ref.getRemote();
                    }
                    if (interfaceClass[0] == null) {
                        interfaceClass[0] = ref.getEjbClass();
                    }
                    ejbRefInjection = generateEjbInjection(workingCopy, make, interfaceClass[0], onClassPath);

                    if (ejbRefInjection != null) {
                        String comment1 = "Add business logic below. (Right-click in editor and choose"; //NOI18N
                        String comment2 = "\"Web Service > Add Operation\""; //NOI18N
                        make.addComment(ejbRefInjection, Comment.create(Comment.Style.LINE, 0, 0, 4, comment1), false);
                        make.addComment(ejbRefInjection, Comment.create(Comment.Style.LINE, 0, 0, 4, comment2), false);

                        ClassTree javaClass = workingCopy.getTrees().getTree(typeElement);
                        ClassTree modifiedClass = make.insertClassMember(javaClass, 0, ejbRefInjection);

                        if (onClassPath[0]) {
                            TypeElement beanInterface = workingCopy.getElements().getTypeElement(interfaceClass[0]);
                            modifiedClass = generateMethods(workingCopy, make, typeElement, modifiedClass, beanInterface);
                        }

                        workingCopy.rewrite(javaClass, modifiedClass);
                    }
                }
            }
            @Override
            public void cancel() {
            }
        };
        final Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                try {
                    targetSource.runModificationTask(modificationTask).commit();
                    if (!onClassPath[0]) {
                        DialogDisplayer.getDefault().notify(
                                new NotifyDescriptor.Message(
                                        NbBundle.getMessage(JaxWsServiceCreator.class, 
                                                "MSG_EJB_NOT_ON_CLASSPATH", 
                                                interfaceClass[0], targetFo.getName()),
                                                    NotifyDescriptor.WARNING_MESSAGE));
                    }
                }
                catch( IOException e ){
                    Logger.getLogger(JaxWsServiceCreator.class.getCanonicalName()).
                        log(Level.WARNING , null, e);
                }
            }
        };
        final String title = NbBundle.getMessage(JaxWsServiceCreator.class, 
                "LBL_GenDelegateMethods");              // NOI18N
        if ( SwingUtilities.isEventDispatchThread()){
            ScanDialog.runWhenScanFinished( runnable , title);
        }
        else {
            SwingUtilities.invokeLater( new Runnable() {
                
                @Override
                public void run() {
                    ScanDialog.runWhenScanFinished( runnable , title);                    
                }
            });
        }
        
    }
    private VariableTree generateEjbInjection(WorkingCopy workingCopy, TreeMaker make, String beanInterface, boolean[] onClassPath) {

        TypeElement ejbAnElement = workingCopy.getElements().getTypeElement("javax.ejb.EJB"); //NOI18N
        TypeElement interfaceElement = workingCopy.getElements().getTypeElement(beanInterface); //NOI18N

        AnnotationTree ejbAnnotation = make.Annotation(
                make.QualIdent(ejbAnElement),
                Collections.<ExpressionTree>emptyList());
        // create method modifier: public and no annotation
        ModifiersTree methodModifiers = make.Modifiers(
                Collections.<Modifier>singleton(Modifier.PRIVATE),
                Collections.<AnnotationTree>singletonList(ejbAnnotation));

        onClassPath[0] = interfaceElement != null;

        return make.Variable(
                methodModifiers,
                "ejbRef", //NOI18N
                onClassPath[0] ? make.Type(interfaceElement.asType()) : make.Identifier(beanInterface),
                null);
    }

    private ClassTree generateMethods(WorkingCopy workingCopy,
            TreeMaker make,
            TypeElement classElement,
            ClassTree modifiedClass,
            TypeElement beanInterface) throws IOException {

        GeneratorUtilities utils = GeneratorUtilities.get(workingCopy);

        List<? extends Element> interfaceElements = beanInterface.getEnclosedElements();
        TypeElement webMethodEl = workingCopy.getElements().getTypeElement("javax.jws.WebMethod"); //NOI18N
        assert (webMethodEl != null);
        if (webMethodEl == null) {
            return modifiedClass;
        }

        Set<String> operationNames = new HashSet<String>();
        for (Element el : interfaceElements) {
            if (el.getKind() == ElementKind.METHOD) {
                ExecutableElement methodEl = (ExecutableElement) el;
                MethodTree method = utils.createAbstractMethodImplementation(classElement, methodEl);

                Name methodName = methodEl.getSimpleName();
                boolean isVoid = workingCopy.getTypes().getNoType(TypeKind.VOID) == methodEl.getReturnType();

                String operationName = findUniqueOperationName(operationNames, methodName.toString());
                operationNames.add(operationName);

                // generate @WebMethod annotation
                AssignmentTree opName = make.Assignment(make.Identifier("operationName"), make.Literal(operationName)); //NOI18N

                AnnotationTree webMethodAn = make.Annotation(
                        make.QualIdent(webMethodEl),
                        Collections.<ExpressionTree>singletonList(opName));
                ModifiersTree modifiersTree = make.Modifiers(
                        Collections.<Modifier>singleton(Modifier.PUBLIC),
                        Collections.<AnnotationTree>singletonList(webMethodAn));

                // generate @RequestWrapper and @RequestResponse annotations
                if (!methodName.contentEquals(operationName)) {
                    TypeElement requestWrapperEl = workingCopy.getElements().getTypeElement("javax.xml.ws.RequestWrapper"); //NOI18N
                    TypeElement responseWrapperEl = workingCopy.getElements().getTypeElement("javax.xml.ws.ResponseWrapper"); //NOI18N
                    AssignmentTree className = make.Assignment(make.Identifier("className"), make.Literal(operationName)); //NOI18N
                    AnnotationTree requestWrapperAn = make.Annotation(
                            make.QualIdent(requestWrapperEl),
                            Collections.<ExpressionTree>singletonList(className));
                    modifiersTree = make.addModifiersAnnotation(modifiersTree, requestWrapperAn);

                    if (!isVoid) { // only if not void
                        className = make.Assignment(make.Identifier("className"), make.Literal(operationName + "Response")); //NOI18N
                        AnnotationTree responseWrapperAn = make.Annotation(
                                make.QualIdent(responseWrapperEl),
                                Collections.<ExpressionTree>singletonList(className));
                        modifiersTree = make.addModifiersAnnotation(modifiersTree, responseWrapperAn);
                    }
                }

                // generate @Oneway annotation
                if (isVoid && method.getThrows().isEmpty()) {
                    TypeElement onewayEl = workingCopy.getElements().getTypeElement("javax.jws.Oneway"); //NOI18N
                    AnnotationTree onewayAn = make.Annotation(
                            make.QualIdent(onewayEl),
                            Collections.<ExpressionTree>emptyList());
                    modifiersTree = make.addModifiersAnnotation(modifiersTree, onewayAn);
                }
                // parameters
                List<? extends VariableTree> params = method.getParameters();
                List<VariableTree> newParams = new ArrayList<VariableTree>();
                if (params.size() > 0) {
                    TypeElement paramEl = workingCopy.getElements().getTypeElement("javax.jws.WebParam"); //NOI18N
                    for (VariableTree param: params) {
                        String paramName = param.getName().toString();
                        AssignmentTree nameAttr = make.Assignment(make.Identifier("name"), make.Literal(paramName)); //NOI18N
                        AnnotationTree paramAn = make.Annotation(
                                make.QualIdent(paramEl),
                                Collections.<ExpressionTree>singletonList(nameAttr));
                        ModifiersTree paramModifierTree = make.addModifiersAnnotation(param.getModifiers(), paramAn);
                        newParams.add(make.Variable(paramModifierTree, param.getName(), param.getType(), null));
                    }
                }

                // method body
                List<ExpressionTree> arguments = new ArrayList<ExpressionTree>();
                for (VariableElement ve : methodEl.getParameters()) {
                    arguments.add(make.Identifier(ve.getSimpleName()));
                }
                MethodInvocationTree inv = make.MethodInvocation(
                        Collections.<ExpressionTree>emptyList(),
                        make.MemberSelect(make.Identifier("ejbRef"), methodName), //NOI18N
                        arguments);

                StatementTree statement = isVoid ? make.ExpressionStatement(inv) : make.Return(inv);

                BlockTree body = make.Block(Collections.singletonList(statement), false);

                MethodTree delegatingMethod = make.Method(
                        modifiersTree,
                        method.getName(),
                        method.getReturnType(),
                        method.getTypeParameters(),
                        newParams,
                        method.getThrows(),
                        body,
                        null);
                modifiedClass = make.addClassMember(modifiedClass, delegatingMethod);
            }
        }
        return modifiedClass;
    }

    private String findUniqueOperationName(Set<String> existingNames, String operationName) {
        if (!existingNames.contains(operationName)) {
            return operationName;
        } else {
            int i = 1;
            String newName = operationName + "_1"; //NOI18N
            while (existingNames.contains(newName)) {
                newName = operationName + "_" + String.valueOf(++i); //NOI18N
            }
            return newName;
        }
    }
}
