/*******************************************************************************
* Copyright (c) 2006 IONA Technologies PLC
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* 
* Contributors:
*     IONA Technologies PLC - initial API and implementation
*******************************************************************************/
/*
 * Created on May 30, 2006
 *
 * Copyright 2005 by IONA Technologies PLC, Inc.
 *
 * All rights reserved.
 *
 */
package org.eclipse.stp.sc.common.builders;

import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.stp.common.logging.LoggingProxy;



/**
 * This builder is used to build java code with annotation. It is done by call the javaToWsdl generator.
 */
public abstract class ScJavaBuilder extends IncrementalProjectBuilder {
        
    private static final LoggingProxy LOG = LoggingProxy.getlogger(ScJavaBuilder.class);
    
    public ScJavaBuilder() {
        super();
    }

    @SuppressWarnings("unchecked")
	@Override
    protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
        throws CoreException {
        if (kind == IncrementalProjectBuilder.FULL_BUILD) {
            fullBuild(monitor);
        } else {
            IResourceDelta delta = getDelta(getProject());

            if (delta == null) {
                fullBuild(monitor);
            } else {
                incrementalBuild(delta, monitor);
            }
        }

        return null;
    }

    /**
     * build every java with ws-annotation files within the project
     * @param monitor, the progress monitor
     * @throws CoreException get status within CoreException will have BUILD_FAILED 
     * code and error message string
     */
    protected void fullBuild(final IProgressMonitor monitor)
        throws CoreException {
        LOG.debug("fullBuild for project:" + getProject().getName());
        getProject().accept(new ScBuildVisitor());
        getProject().refreshLocal(IProject.DEPTH_INFINITE, monitor);
    }

    protected void incrementalBuild(IResourceDelta delta,
        IProgressMonitor monitor) throws CoreException {
        // the visitor does the work.
        LOG.debug("incrementalBuild for project:" + getProject().getName());
        delta.accept(new ScBuildDeltaVisitor());
        getProject().refreshLocal(IProject.DEPTH_INFINITE, monitor);
    }

    /**
     * clean the generated wsdl. This will delete /project/wsdl dir and all contains under that dir
     * @param monitor, the progress monitor
     * @throws CoreException
     */
    abstract protected void clean(IProgressMonitor monitor) throws CoreException; //{
//        LOG.debug("clean for the project:" + getProject().getName());
//        IFolder wsdlFolder = WorkspaceManager.getWSDLFolder(getProject());
//        wsdlFolder.delete(true, monitor);
//        getProject().refreshLocal(IProject.DEPTH_INFINITE, null);
//    }

    
    /**
     * setup the javatowsdl generate in the initialize
     */
    protected void startupOnInitialize() {
    }

    /**
     * visit the resource file within project.
     * call javatowsdl if it is java file and has WebService annotation
     * @param res
     * @throws CoreException
     */
    private void visitResourceFile(IResource res) throws CoreException {
        if (!(res instanceof IFile)) {
            return;
        }

        IFile file = (IFile)res;
        if (file == null || file.getFileExtension()==null) {
        	return;
        }
        
        if (!file.getFileExtension().equals("java")) {
            return;
        }

        if (checkAnnotation(file)) {
            buildOneJavaFile(file);
        }
    }

    /**
     *
     * @param res
     * @throws CoreException
     */
    abstract protected void removeResourceFile(IResource res) throws CoreException ;//{
//        if (!(res instanceof IFile)) {
//            return;
//        }
//
//        IFile file = (IFile)res;
//
//        if (!file.getFileExtension().equals("java")) {
//            return;
//        }
//
//        if (checkAnnotation(file)) {
//            LOG.debug("WebService java file has been removed:"
//                + file.getFullPath());
//
//            String clsName = JDTUtils.getJavaClassNameFromFile(file);
//
//            if (clsName.lastIndexOf(".") > 0) {
//                clsName = clsName.substring(clsName.lastIndexOf("."));
//            }
//
//            String wsdlName = clsName + ".wsdl";
//            LOG.debug("  need to remove:" + wsdlName);
//
//            IFolder folder = WorkspaceManager.getWSDLFolder(getProject());
//            IResource wsdlResource = folder.findMember(wsdlName);
//
//            if (wsdlResource.exists()) {
//                LOG.debug("delete wsdl resource:"
//                    + wsdlResource.getFullPath());
//                wsdlResource.delete(IResource.FORCE, null);
//            }
//        }
//    }

    class ScBuildVisitor implements IResourceVisitor {
        public boolean visit(IResource res) throws CoreException {
            //build the specified resource.
            visitResourceFile(res);

            //return true to continue visiting children.
            return true;
        }
    }

    class ScBuildDeltaVisitor implements IResourceDeltaVisitor {
        public boolean visit(IResourceDelta delta) throws CoreException {
            IResource res = delta.getResource();

            switch (delta.getKind()) {
            case IResourceDelta.ADDED:
            case IResourceDelta.CHANGED:
                visitResourceFile(res);

                break;

            case IResourceDelta.REMOVED:
                LOG.debug("DeltaVistor, removed resource:"
                    + res.getFullPath());
                try {
                    removeResourceFile(res);
                } catch (Exception e) {
                    LOG.error("builder error", e);
                }

                break;
            default:
                break;
            }

            return true;
        }
    }
    
    /**
     * the subclass must implement this buildOneJavaFile method to call correct generator to 
     * generate wsdl file
     * @param javaFile
     * @throws CoreException
     */
    abstract protected void buildOneJavaFile(IFile javaFile) throws CoreException;
    
    /**
     * check to see if the java source file contains expected annotations.
     * for example:
     * <li>The jax-ws javatowsdl builder will check if the @WebService annotation
     * exists or not.
     * <li>The sca javatowsdl builder will check if the @Service annotation exists or not
     * @param javaFile
     * @return
     */
    abstract protected boolean  checkAnnotation(IFile javaFile);
    
}
