/*
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed 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.apache.axis.wsdl.toJava;

import org.apache.axis.Constants;
import org.apache.axis.constants.Scope;
import org.apache.axis.description.ServiceDesc;
import org.apache.axis.encoding.TypeMapping;
import org.apache.axis.encoding.TypeMappingRegistryImpl;
import org.apache.axis.i18n.Messages;
import org.apache.axis.utils.ClassUtils;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.wsdl.gen.GeneratorFactory;
import org.apache.axis.wsdl.gen.Parser;
import org.apache.axis.wsdl.symbolTable.BaseTypeMapping;
import org.apache.axis.wsdl.symbolTable.SymTabEntry;
import org.apache.axis.wsdl.symbolTable.SymbolTable;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.wsdl.WSDLException;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

/**
 * This class produces java files for stubs, skeletons, and types from a
 * WSDL document.
 * 
 * @author Russell Butek (butek@us.ibm.com)
 * @author Tom Jordahl (tjordahl@macromedia.com)
 * @author Rich Scheuerle (scheu@us.ibm.com)
 * @author Steve Graham (sggraham@us.ibm.com)
 */
public class Emitter extends Parser {

    /** Field DEFAULT_NSTOPKG_FILE */
    public static final String DEFAULT_NSTOPKG_FILE = "NStoPkg.properties";

    /** Field namespaceMap */
    protected HashMap namespaceMap = new HashMap();

    /** Field typeMappingVersion */
    protected String typeMappingVersion = "1.2";

    /** Field baseTypeMapping */
    protected BaseTypeMapping baseTypeMapping = null;

    /** Field namespaces */
    protected Namespaces namespaces = null;

    /** Field NStoPkgFilename */
    protected String NStoPkgFilename = null;

    /** Field bEmitServer */
    private boolean bEmitServer = false;

    /** Field bDeploySkeleton */
    private boolean bDeploySkeleton = false;

    /** Field bEmitTestCase */
    private boolean bEmitTestCase = false;

    /** Field bGenerateAll */
    private boolean bGenerateAll = false;

    /** Field bHelperGeneration */
    private boolean bHelperGeneration = false;
    
    private boolean bBuildFileGeneration = false;

    private boolean typeCollisionProtection = true;

    /** Check if URL endpoints are valid or not */
    private boolean allowInvalidURL = false;

    /** Field packageName */
    private String packageName = null;

    /** Field scope */
    private Scope scope = null;

    /** Field fileInfo */
    private GeneratedFileInfo fileInfo = new GeneratedFileInfo();

    /** Field delayedNamespacesMap */
    private HashMap delayedNamespacesMap = new HashMap();

    /** Field outputDir */
    private String outputDir = null;
    
    /** Field nsIncludes - defines a list of namespaces to specifically
     * include in the generated source code. If non-empty, anything
     * not in this list should be excluded. If empty, everything in this
     * and not specifically excluded should be generated. 
     */
    protected List nsIncludes = new ArrayList();
    
    /** Field nsIncludes - defines a list of namespaces to specifically 
     * exclude from generated source code. Any entry in this list that 
     * is in conflict with the includes list should be ignored and 
     * generated.
     */
    protected List nsExcludes = new ArrayList();
    
    /** Field properties - defines a set of general purpose properties
     * that can be used by custom JavaGeneratorFactories.
     */
    protected List properties = new ArrayList();
    
    /**
     * Field implementationClassName - defines a non default classname for the actual
     * implementation class. Particularly useful when exporting a webservice directly
     * from the java implementation.
     */
	private String implementationClassName = null;
	
    /** Field defaultTM */
    private TypeMapping defaultTM = null;       // Default TM

    private TypeMappingRegistryImpl tmr = new TypeMappingRegistryImpl();
    
    /** The mapping of qname to its corresponding java type generated by Java2Wsdl emitter. For deploy mode roundtripping use. */
    private HashMap qName2ClassMap;
	
	/** The ServiceDesc. For deploy mode roundtripping use. */
    private ServiceDesc serviceDesc;
	
	/** The deploy mode flag */
    private boolean isDeploy;

    /**
     * Default constructor.
     */
    public Emitter() {
        setFactory(new JavaGeneratorFactory(this));
    }    // ctor

    // /////////////////////////////////////////////////
    // 
    // Command line switches
    // 

    /**
     * Turn on/off server skeleton creation
     * 
     * @param value 
     */
    public void setServerSide(boolean value) {
        this.bEmitServer = value;
    }    // setServerSide

    /**
     * Indicate if we should be emitting server side code and deploy/undeploy
     * 
     * @return 
     */
    public boolean isServerSide() {
        return bEmitServer;
    }    // isServerSide

    /**
     * Turn on/off server skeleton deploy
     * 
     * @param value 
     */
    public void setSkeletonWanted(boolean value) {
        bDeploySkeleton = value;
    }    // setSkeletonWanted

    /**
     * Indicate if we should be deploying skeleton or implementation
     * 
     * @return 
     */
    public boolean isSkeletonWanted() {
        return bDeploySkeleton;
    }    // isSkeletonWanted

    /**
     * Turn on/off Helper class generation
     * 
     * @param value 
     */
    public void setHelperWanted(boolean value) {
        bHelperGeneration = value;
    }    // setHelperWanted

    /**
     * Indicate if we should be generating Helper classes
     * 
     * @return 
     */
    public boolean isHelperWanted() {
        return bHelperGeneration;
    }    // isHelperWanted

    /**
     * Turn on/off test case creation
     * 
     * @param value 
     */
    public void setTestCaseWanted(boolean value) {
        this.bEmitTestCase = value;
    }    // setTestCaseWanted

    /**
     * Method isTestCaseWanted
     * 
     * @return 
     */
    public boolean isTestCaseWanted() {
        return bEmitTestCase;
    }    // isTestCaseWanted

    /**
     * get the build file genaeration state
     * @return
     */
    public boolean isBuildFileWanted(){
        return bBuildFileGeneration;
    }
    
    /**
     * turn the build file genaration ON
     * @param value
     */
    public void setBuildFileWanted(boolean value){
        bBuildFileGeneration = value;
    }

    /**
     * By default, code is generated only for referenced elements.
     * Call bGenerateAll(true) and WSDL2Java will generate code for all
     * elements in the scope regardless of whether they are
     * referenced.  Scope means:  by default, all WSDL files; if
     * generateImports(false), then only the immediate WSDL file.
     * 
     * @param all 
     */
    public void setAllWanted(boolean all) {
        bGenerateAll = all;
    }    // setAllWanted

    /**
     * Method isAllWanted
     * 
     * @return 
     */
    public boolean isAllWanted() {
        return bGenerateAll;
    }    // isAllWanted

    /**
     * Method getNamespaces
     * 
     * @return 
     */
    public Namespaces getNamespaces() {
        return namespaces;
    }    // getNamespaces

    /**
     * Set the output directory to use in emitted source files
     * 
     * @param outputDir 
     */
    public void setOutputDir(String outputDir) {
        this.outputDir = outputDir;
    }

    /**
     * Get the output directory to use for emitted source files
     * 
     * @return 
     */
    public String getOutputDir() {
        return outputDir;
    }

    /**
     * Get global package name to use instead of mapping namespaces
     * 
     * @return 
     */
    public String getPackageName() {
        return packageName;
    }

    /**
     * Set a global package name to use instead of mapping namespaces
     * 
     * @param packageName 
     */
    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

    /**
     * Set the scope for the deploy.xml file.
     * 
     * @param scope One of 'null',
     *              Scope.APPLICATION, Scope.REQUEST, Scope.SESSION.
     *              Anything else is equivalent to 'null' null and no explicit
     *              scope tag will appear in deploy.xml.
     */
    public void setScope(Scope scope) {
        this.scope = scope;
    }    // setScope

    /**
     * Get the scope for the deploy.xml file.
     * 
     * @return 
     */
    public Scope getScope() {
        return scope;
    }    // getScope

    /**
     * Set the NStoPkg mappings filename.
     * 
     * @param NStoPkgFilename 
     */
    public void setNStoPkg(String NStoPkgFilename) {

        if (NStoPkgFilename != null) {
            this.NStoPkgFilename = NStoPkgFilename;
        }
    }    // setNStoPkg

    /**
     * Set a map of namespace -> Java package names
     * 
     * @param map 
     */
    public void setNamespaceMap(HashMap map) {
        delayedNamespacesMap = map;
    }

    /**
     * Get the map of namespace -> Java package names
     * 
     * @return 
     */
    public HashMap getNamespaceMap() {
        return delayedNamespacesMap;
    }
    
    /** Sets the list of namespaces to specifically include
     * in the generated code.
     */
    public void setNamespaceIncludes(List nsIncludes) {
        this.nsIncludes = nsIncludes;
    }

    /** Returns the list of namespaces specifically excluded
     * from the generated code.
     */
    public List getNamespaceIncludes() {
        return this.nsIncludes;
    }
    
    /** Sets the list of namespaces to specifically exclude
     * from the generated source.
     */
    public void setNamespaceExcludes(List nsExcludes) {
        this.nsExcludes = nsExcludes;
    }
    
    /** Returns the list of excludes to specifically exclude
     * from the generated source.
     */
    public List getNamespaceExcludes() {
        return this.nsExcludes;
    }
    
    /** Sets the list of extension properties for custom 
     * JavaGeneratorFactories.
     */ 
    public void setProperties(List properties) {
        this.properties = properties;
    }
    
    /** Gets the list of extension properties for custom
     * JavaGeneratorFactories.
     */ 
    public List getProperties() {
        return this.properties;
    }

    /**
     * Returns the default <code>TypeMapping</code> used by the service
     * 
     * @return the default <code>TypeMapping</code> used by the service
     */
    public TypeMapping getDefaultTypeMapping() {
        if (defaultTM == null) {
            defaultTM =
                    (TypeMapping)tmr.getTypeMapping(Constants.URI_SOAP11_ENC);
        }
        return defaultTM;
    }

    /**
     * Sets the default <code>TypeMapping</code> used by the service
     * 
     * @param defaultTM the default <code>TypeMapping</code> used by the service
     */
    public void setDefaultTypeMapping(TypeMapping defaultTM) {
        this.defaultTM = defaultTM;
    }
    
    /**
     * Sets the <code>WriterFactory Class</code> to use
     * 
     * @param factory the name of the factory <code>Class</code>
     */
    public void setFactory(String factory) {

        try {
            Class clazz = ClassUtils.forName(factory);
            GeneratorFactory genFac;
            try {
                Constructor ctor = clazz.getConstructor(new Class[]{
                    getClass()});

                genFac = (GeneratorFactory) ctor.newInstance(new Object[]{
                    this});
            } catch (NoSuchMethodException ex) {
                genFac = (GeneratorFactory) clazz.newInstance();
            }

            setFactory(genFac);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }    // setFactory

    // 
    // Command line switches
    // 
    // /////////////////////////////////////////////////

    /**
     * Returns an object which contains of information on all generated files
     * including the class name, filename and a type string.
     * 
     * @return An org.apache.axis.wsdl.toJava.GeneratedFileInfo object
     * @see org.apache.axis.wsdl.toJava.GeneratedFileInfo
     */
    public GeneratedFileInfo getGeneratedFileInfo() {
        return fileInfo;
    }

    /**
     * This method returns a list of all generated class names.
     * 
     * @return 
     */
    public List getGeneratedClassNames() {
        return fileInfo.getClassNames();
    }

    /**
     * This method returns a list of all generated file names.
     * 
     * @return 
     */
    public List getGeneratedFileNames() {
        return fileInfo.getFileNames();
    }

    /**
     * Get the Package name for the specified namespace
     * 
     * @param namespace 
     * @return 
     */
    public String getPackage(String namespace) {
        return namespaces.getCreate(namespace);
    }

    /**
     * Get the Package name for the specified QName
     * 
     * @param qName 
     * @return 
     */
    public String getPackage(QName qName) {
        return getPackage(qName.getNamespaceURI());
    }

    /**
     * Convert the specified QName into a full Java Name.
     * 
     * @param qName 
     * @return 
     */
    public String getJavaName(QName qName) {

        // If this is one of our special 'collection' qnames.
        // get the element type and append []
        if (qName.getLocalPart().indexOf("[") > 0) {
            String localPart = qName.getLocalPart().substring(0,
                    qName.getLocalPart().indexOf("["));
            QName eQName = new QName(qName.getNamespaceURI(), localPart);

            return getJavaName(eQName) + "[]";
        }

        // Handle the special "java" namespace for types
        if (qName.getNamespaceURI().equalsIgnoreCase("java")) {
            return qName.getLocalPart();
        }

        // The QName may represent a base java name, so check this first
        String fullJavaName =
                getFactory().getBaseTypeMapping().getBaseName(qName);

        if (fullJavaName != null) {
            return fullJavaName;
        }

        fullJavaName = getJavaNameHook(qName);
        if (fullJavaName != null) {
            return fullJavaName;
        }
        // Use the namespace uri to get the appropriate package
        String pkg = getPackage(qName.getNamespaceURI());

        if (pkg != null && pkg.length() > 0) {
            fullJavaName = pkg + "."
                    + Utils.xmlNameToJavaClass(qName.getLocalPart());
        } else {
            fullJavaName = Utils.xmlNameToJavaClass(qName.getLocalPart());
        }

        return fullJavaName;
    }    // getJavaName
    
    protected String getJavaNameHook(QName qname) { return null; }
    
    
    /**
     * @param typeQName QName for containing xml type
     * @param xmlName QName for element
     * @return
     */
    public String getJavaVariableName(QName typeQName, QName xmlName, boolean isElement) {
        String javaName = getJavaVariableNameHook(typeQName, xmlName, isElement);
        if (javaName == null) {
            String elemName = Utils.getLastLocalPart(xmlName.getLocalPart());            
            javaName = Utils.xmlNameToJava(elemName);
        }
        return javaName;
    }
        
    protected String getJavaVariableNameHook(QName typeQName, QName xmlName, boolean isElement) {
        return null;
    }
        
    

    /**
     * Emit appropriate Java files for a WSDL at a given URL.
     * <p/>
     * This method will time out after the number of milliseconds specified
     * by our timeoutms member.
     * 
     * @param wsdlURL 
     * @throws Exception 
     */
    public void run(String wsdlURL) throws Exception {
        setup();
        super.run(wsdlURL);
    }    // run

    /**
     * Call this method if your WSDL document has already been
     * parsed as an XML DOM document.
     * 
     * @param context context This is directory context for the Document.
     *                If the Document were from file "/x/y/z.wsdl" then the context
     *                could be "/x/y" (even "/x/y/z.wsdl" would work).
     *                If context is null, then the context becomes the current directory.
     * @param doc     doc This is the XML Document containing the WSDL.
     * @throws IOException                  
     * @throws SAXException                 
     * @throws WSDLException                
     * @throws ParserConfigurationException 
     */
    public void run(String context, Document doc)
            throws IOException, SAXException, WSDLException,
            ParserConfigurationException {
        setup();
        super.run(context, doc);
    }    // run

    /**
     * Method setup
     * 
     * @throws IOException 
     */
    private void setup() throws IOException {

        if (baseTypeMapping == null) {
            setTypeMappingVersion(typeMappingVersion);
        }

        getFactory().setBaseTypeMapping(baseTypeMapping);

        namespaces = new Namespaces(outputDir);

        if (packageName != null) {
            namespaces.setDefaultPackage(packageName);
        } else {

            // First, read the namespace mapping file - configurable, by default
            // NStoPkg.properties - if it exists, and load the namespaceMap HashMap
            // with its data.
            getNStoPkgFromPropsFile(namespaces);

            if (delayedNamespacesMap != null) {
                namespaces.putAll(delayedNamespacesMap);
            }
        }
    }    // setup

    /**
     * Method sanityCheck
     * 
     * @param symbolTable 
     */
    protected void sanityCheck(SymbolTable symbolTable) {

        Iterator it = symbolTable.getHashMap().values().iterator();

        while (it.hasNext()) {
            Vector v = (Vector) it.next();

            for (int i = 0; i < v.size(); ++i) {
                SymTabEntry entry = (SymTabEntry) v.elementAt(i);
                String namespace = entry.getQName().getNamespaceURI();
                String packageName =
                        org.apache.axis.wsdl.toJava.Utils.makePackageName(
                                namespace);
                String localName = entry.getQName().getLocalPart();

                if (localName.equals(packageName)
                        && packageName.equals(
                                namespaces.getCreate(namespace))) {
                    packageName += "_pkg";

                    namespaces.put(namespace, packageName);
                }
            }
        }
    }

    /**
     * Tries to load the namespace-to-package mapping file.
     * <ol>
     * <li>if a file name is explicitly set using <code>setNStoPkg()</code>, tries
     * to load the mapping from this file. If this fails, the built-in default
     * mapping is used.
     * <p/>
     * <li>if no file name is set, tries to load the file <code>DEFAULT_NSTOPKG_FILE</code>
     * as a java resource. If this fails, the built-in dfault mapping is used.
     * </ol>
     * 
     * @param namespaces a hashmap which is filled with the namespace-to-package mapping
     *                   in this method
     * @throws IOException 
     * @see #setNStoPkg(String)
     * @see #DEFAULT_NSTOPKG_FILE
     * @see org.apache.axis.utils.ClassUtils#getResourceAsStream(java.lang.Class,String)
     */
    private void getNStoPkgFromPropsFile(HashMap namespaces)
            throws IOException {

        Properties mappings = new Properties();

        if (NStoPkgFilename != null) {
            try {
                mappings.load(new FileInputStream(NStoPkgFilename));

                if (verbose) {
                    System.out.println(
                            Messages.getMessage(
                                    "nsToPkgFileLoaded00", NStoPkgFilename));
                }
            } catch (Throwable t) {

                // loading the custom mapping file failed. We do not try
                // to load the mapping from a default mapping file.
                throw new IOException(
                        Messages.getMessage(
                                "nsToPkgFileNotFound00", NStoPkgFilename));
            }
        } else {
            try {
                mappings.load(new FileInputStream(DEFAULT_NSTOPKG_FILE));

                if (verbose) {
                    System.out.println(
                            Messages.getMessage(
                                    "nsToPkgFileLoaded00", DEFAULT_NSTOPKG_FILE));
                }
            } catch (Throwable t) {
                try {
                    mappings.load(ClassUtils.getResourceAsStream(Emitter.class,
                            DEFAULT_NSTOPKG_FILE));

                    if (verbose) {
                        System.out.println(
                                Messages.getMessage(
                                        "nsToPkgDefaultFileLoaded00",
                                        DEFAULT_NSTOPKG_FILE));
                    }
                } catch (Throwable t1) {

                    // loading the default mapping file failed.
                    // The built-in default mapping is used
                    // No message is given, since this is generally what happens
                }
            }
        }

        Enumeration keys = mappings.propertyNames();

        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();

            namespaces.put(key, mappings.getProperty(key));
        }
    }    // getNStoPkgFromPropsFile

    /**
     * Get the typemapping version
     */
    public String getTypeMappingVersion() {
        return typeMappingVersion;    
    }
    
    /**
     * Method setTypeMappingVersion
     * 
     * @param typeMappingVersion 
     */
    public void setTypeMappingVersion(String typeMappingVersion) {
        this.typeMappingVersion = typeMappingVersion;
        tmr.doRegisterFromVersion(typeMappingVersion);
        baseTypeMapping = new BaseTypeMapping() {

            final TypeMapping defaultTM = getDefaultTypeMapping();

            public String getBaseName(QName qNameIn) {

                javax.xml.namespace.QName qName =
                        new javax.xml.namespace.QName(qNameIn.getNamespaceURI(),
                                qNameIn.getLocalPart());
                Class cls =
                        defaultTM.getClassForQName(qName);

                if (cls == null) {
                    return null;
                } else {
                    return JavaUtils.getTextClassName(cls.getName());
                }
            }
        };
    }

    // The remainder are deprecated methods.

    /**
     * Get the GeneratorFactory.
     * 
     * @return 
     * @deprecated Call getFactory instead.  This doesn't return
     *             a WriterFactory, it returns a GeneratorFactory.
     */
    public GeneratorFactory getWriterFactory() {
        return getFactory();
    }    // getWriterFactory

    /**
     * Call this method if you have a uri for the WSDL document
     * 
     * @param uri wsdlURI the location of the WSDL file.
     * @throws Exception 
     * @deprecated Call run(uri) instead.
     */
    public void emit(String uri) throws Exception {
        run(uri);
    }    // emit

    /**
     * Call this method if your WSDL document has already been
     * parsed as an XML DOM document.
     * 
     * @param context context This is directory context for the Document.
     *                If the Document were from file "/x/y/z.wsdl" then the context could be "/x/y"
     *                (even "/x/y/z.wsdl" would work).  If context is null, then the context
     *                becomes the current directory.
     * @param doc     doc This is the XML Document containing the WSDL.
     * @throws IOException                  
     * @throws SAXException                 
     * @throws WSDLException                
     * @throws ParserConfigurationException 
     * @deprecated Call run(context, doc) instead.
     */
    public void emit(String context, Document doc)
            throws IOException, SAXException, WSDLException,
            ParserConfigurationException {
        run(context, doc);
    }    // emit

    /**
     * Turn on/off server-side binding generation
     * 
     * @param value 
     * @deprecated Use setServerSide(value)
     */
    public void generateServerSide(boolean value) {
        setServerSide(value);
    }

    /**
     * Indicate if we should be emitting server side code and deploy/undeploy
     * 
     * @return 
     * @deprecated Use isServerSide()
     */
    public boolean getGenerateServerSide() {
        return isServerSide();
    }

    /**
     * Turn on/off server skeleton deploy
     * 
     * @param value 
     * @deprecated Use setSkeletonWanted(value)
     */
    public void deploySkeleton(boolean value) {
        setSkeletonWanted(value);
    }

    /**
     * Indicate if we should be deploying skeleton or implementation
     * 
     * @return 
     * @deprecated Use isSkeletonWanted()
     */
    public boolean getDeploySkeleton() {
        return isSkeletonWanted();
    }

    /**
     * Turn on/off Helper class generation
     * 
     * @param value 
     * @deprecated Use setHelperWanted(value)
     */
    public void setHelperGeneration(boolean value) {
        setHelperWanted(value);
    }

    /**
     * Indicate if we should be generating Helper classes
     * 
     * @return 
     * @deprecated Use isHelperWanted()
     */
    public boolean getHelperGeneration() {
        return isHelperWanted();
    }

    /**
     * Turn on/off generation of elements from imported files.
     * 
     * @param generateImports 
     * @deprecated Use setImports(generateImports)
     */
    public void generateImports(boolean generateImports) {
        setImports(generateImports);
    }    // generateImports

    /**
     * Turn on/off debug messages.
     * 
     * @param value 
     * @deprecated Use setDebug(value)
     */
    public void debug(boolean value) {
        setDebug(value);
    }    // debug

    /**
     * Return the status of the debug switch.
     * 
     * @return 
     * @deprecated Use isDebug()
     */
    public boolean getDebug() {
        return isDebug();
    }    // getDebug

    /**
     * Turn on/off verbose messages
     * 
     * @param value 
     * @deprecated Use setVerbose(value)
     */
    public void verbose(boolean value) {
        setVerbose(value);
    }

    /**
     * Return the status of the verbose switch
     * 
     * @return 
     * @deprecated Use isVerbose()
     */
    public boolean getVerbose() {
        return isVerbose();
    }

    /**
     * Turn on/off test case creation
     * 
     * @param value 
     * @deprecated Use setTestCaseWanted()
     */
    public void generateTestCase(boolean value) {
        setTestCaseWanted(value);
    }

    /**
     * @param all 
     * @deprecated Use setAllWanted(all)
     */
    public void generateAll(boolean all) {
        setAllWanted(all);
    }    // generateAll
    
    /**
     * Get the type collision protection setting
     * @return
     */
    public boolean isTypeCollisionProtection(){
        return this.typeCollisionProtection;
    }
    
    /**
     * Enable/disable type collision protection
     * @param value
     */
    public void setTypeCollisionProtection(boolean value){
        this.typeCollisionProtection = value;
    }
    
	/**
	 * Get an implementation classname to use instead of the default.
	 * @return
	 */
	public String getImplementationClassName() {
		return implementationClassName;
	}

	/**
	 * Set an implementation classname to use instead of the default.
	 * 
	 * @param implementationClassName 
	 */
	public void setImplementationClassName(String implementationClassName) {
		this.implementationClassName = implementationClassName;
	}
          
    /**
     * @return Returns the allowInvalidURL.
     */
    public boolean isAllowInvalidURL() {
        return allowInvalidURL;
    }

    /**
     * @param allowInvalidURL The allowInvalidURL to set.
     */
    public void setAllowInvalidURL(boolean allowInvalidURL) {
        this.allowInvalidURL = allowInvalidURL;
    }
    
    /**
     * Set the type qname to java class map
     * @param map a type qname to javaclass map (from Java2Wsdl emitter)
     */
    public void setQName2ClassMap(HashMap map) {
        qName2ClassMap = map;
    }

    /**
     * Get the type qname to java class map 
     * @return the type qname to java class map
     */
    public HashMap getQName2ClassMap() {
        return qName2ClassMap;
    }
    
    /** 
     * Retruns the SericeDesc object
     * @return
     */
    public ServiceDesc getServiceDesc() {
        return serviceDesc;
    }    
    
    /**
     * Sets the ServicdDesc object
     * @param serviceDesc ServiceDesc to set
     */
    public void setServiceDesc(ServiceDesc serviceDesc) {
        this.serviceDesc = serviceDesc;
    }
    
    /**
     * Returns the deploy mode flag
     * @return
     */
    public boolean isDeploy() {
        return isDeploy;
    }
    
    /**
     * Sets the deploy mode flag
     * @param isDeploy deploy mode flag
     */
    public void setDeploy(boolean isDeploy) {
        this.isDeploy = isDeploy;
    }
    
    /**
     * Check if the className exists.
     * 
     * @param className className to check
     * @return true if exists, false if not
     */
    protected boolean doesExist(String className) {        
        try {
            ClassUtils.forName(className);
        } catch (ClassNotFoundException e) {
            return false;
        }		
        
        return true;
    }

    public void setWrapArrays(boolean wrapArrays) {
        this.wrapArrays = wrapArrays;
    }
}
