/* * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "Exolab" must not be used to endorse or promote * products derived from this Software without prior written * permission of Intalio, Inc. For written permission, * please contact info@exolab.org. * * 4. Products derived from this Software may not be called "Exolab" * nor may "Exolab" appear in their names without prior written * permission of Intalio, Inc. Exolab is a registered * trademark of Intalio, Inc. * * 5. Due credit should be given to the Exolab Project * (http://www.exolab.org/). * * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 1999-2003 (C) Intalio, Inc. All Rights Reserved. * * This file was originally developed by Keith Visco during the * course of employment at Intalio Inc. * All portions of this file developed by Keith Visco after Jan 19 2005 are * Copyright (C) 2005 Keith Visco. All Rights Reserved. * * $Id$ */ package org.exolab.castor.builder; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.Properties; import java.util.Vector; import org.exolab.castor.builder.util.ClassInfoResolverImpl; import org.exolab.castor.mapping.xml.MappingRoot; import org.exolab.castor.util.dialog.ConsoleDialog; import org.exolab.castor.util.dialog.Dialog; import org.exolab.castor.xml.schema.Annotated; import org.exolab.castor.xml.schema.Schema; import org.exolab.javasource.JClass; /** * A class for maintaining state for the SourceGenerator. * * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a> * @version $Revision$ $Date: 2005-06-22 22:13:21 -0600 (Wed, 22 Jun 2005) $ */ public final class SGStateInfo extends ClassInfoResolverImpl { /** An empty Enumeration to be returned whenever we need an empty Enumeration. */ private static final Enumeration<String> EMPTY_ENUMERATION = new Vector<String>(0).elements(); /** The SourceGenerator is still generating source. */ public static final int NORMAL_STATUS = 0; /** The SourceGenerator has been stopped by an error or by the user. */ public static final int STOP_STATUS = 1; /** The in memory mapping files for each package. */ private Hashtable<String, MappingRoot> _mappings = null; /** The in memory package listings for each package. */ private Hashtable<String, Properties> _packageListings = null; /** The package used when creating new classes. */ private String _packageName; /** Keeps track of which JClass files have been processed. */ private Vector<JClass> _processed = null; /** true if existing source files should not be silently overwritten. */ private boolean _promptForOverwrite = true; /** The schema we are generating source code for. */ private Schema _schema = null; /** true if non-fatal warnings should be suppressed. */ private boolean _suppressNonFatalWarnings = false; /** true if source generation should provide verbose output on its progress. */ private boolean _verbose = false; /** The SourceFactory state. */ private FactoryState _currentFactoryState = null; /** This class allows user interaction when Castor wants to ask a question. */ private Dialog _dialog = null; /** The source generator whose state we track. */ private SourceGenerator _sgen = null; /** Current status of the source generator. */ private int _status = NORMAL_STATUS; /** Maps annotations to generated source code. */ private Map<Annotated, JClass[]> _sourcesByComponent = new HashMap<Annotated, JClass[]>(); /** * A cache of already generated classes (by their class name). */ private Map<String, JClass> _sourcesByName = new HashMap<String, JClass>(); /** * A cache of already generated classes (as part of an imported schema), * keyed by their class name. */ private Map<String, JClass> _importedSourcesByName = new HashMap<String, JClass>(); /** * Creates a new SGStateInfo. * * @param schema the Schema to generate source for * @param sgen the SourceGenerator instance */ protected SGStateInfo(final Schema schema, final SourceGenerator sgen) { super(); _schema = schema; _packageName = ""; _processed = new Vector<JClass>(); _dialog = new ConsoleDialog(); _sgen = sgen; } /** * Get package used when creating new classes. * * @return Package used when creating new classes. */ public String getPackageName() { return _packageName; } /** * Set package used when creating new classes. * * @param packageName Package used when creating new classes. */ protected void setPackageName(final String packageName) { _packageName = packageName; } /** * Binds the given Annotated structure with its generated source classes. * * @param annotated the Annotated structure to add JClass bindings for * @param classes the JClass[] to bind */ public void bindSourceCode(final Annotated annotated, final JClass[] classes) { _sourcesByComponent.put(annotated, classes); for (int i = 0; i < classes.length; i++) { JClass jClass = classes[i]; if (jClass != null) { _sourcesByName.put(jClass.getName(), jClass); } } } //-- bindSourceCode /** * Stores generated sources as processed within an imported schema. * @param importedSourcesByName Generated sources as processed within an imported schema. */ public void storeImportedSourcesByName(final Map<String, JClass> importedSourcesByName) { _importedSourcesByName.putAll(importedSourcesByName); } //-- storeImportedSourcesByName /** * Returns the processed JClass with the given name. If no such JClass has * been marked as processed, null is returned. * * @param className * the JClass name to check against * @return the JClass with the given name */ JClass getProcessed(final String className) { for (int i = 0; i < _processed.size(); i++) { JClass jClass = _processed.elementAt(i); if (jClass.getName().equals(className)) { return jClass; } } return null; } //-- getProcessed /** * Returns the array of JClass for the given Annotated structure or null if * no bindings have been specified for the given Structure. * * @param annotated * the Annotated structure to search * @return the JClass array */ public JClass[] getSourceCode(final Annotated annotated) { return _sourcesByComponent.get(annotated); } //-- getSourceCode /** * Returns the JClass with the given name or null if no bindings have been * specified for a JClass with the name. * * @param className * the name of the JClass * @return the JClass if found */ public JClass getSourceCode(final String className) { return _sourcesByName.get(className); } //-- getSourceCode /** * Returns the JClass with the given name or null if no bindings have been * specified for a JClass with the name. This method consults with JClass * instances imported through a Schema import only. * * @param className * the name of the JClass * @return the (imported) JClass if found */ public JClass getImportedSourceCode(final String className) { return _importedSourcesByName.get(className); } //-- getImportedSourceCode /** * Returns the Mapping file associated with the given filename. * * @param filename * The filename to search for a Mapping File association * @return the Mapping file. */ public MappingRoot getMapping(final String filename) { if (_mappings != null && filename != null) { return _mappings.get(filename); } return null; } //-- getMapping /** * Returns the CDRFile (Properties file) associated with the given filename. * * @param filename filename of the CDR file to be processed * @return the Properties file. */ public Properties getCDRFile(final String filename) { if (_packageListings != null && filename != null) { return _packageListings.get(filename); } return null; } /** * Returns the set of CDR file names. * * @return the set of CDR file names. */ public Enumeration<String> getCDRFilenames() { if (_packageListings == null) { return EMPTY_ENUMERATION; } return _packageListings.keys(); } //-- getCDRFilenames /** * Returns the set of mapping filenames. * * @return the set of mapping filenames. */ public Enumeration<String> getMappingFilenames() { if (_mappings == null) { return EMPTY_ENUMERATION; } return _mappings.keys(); } //-- getMappingFilenames /** * Returns the current status. * * @return the current status. */ public int getStatusCode() { return _status; } //-- getStatusCode /** * Marks the given JClass as having been processed. * * @param jClass the JClass to mark as having been processed. */ void markAsProcessed(final JClass jClass) { //String className = jClass.getName(); if (!_processed.contains(jClass)) { _processed.addElement(jClass); } } //-- markAsProcessed /** * Returns true if the given JClass has been marked as processed. * * @param jClass the JClass to check for being marked as processed * @return true if the given JClass has been marked as processed. */ boolean processed(final JClass jClass) { return _processed.contains(jClass); } //-- processed /** * Returns true if a JClass with the given name has been marked as * processed. * * @param className the JClass name to check against * @return true if a JClass with the given name has been marked as processed */ boolean processed(final String className) { for (int i = 0; i < _processed.size(); i++) { JClass jClass = _processed.elementAt(i); if (jClass.getName().equals(className)) { return true; } } return false; } //-- processed /** * Returns true if existing source files should be prompted before being * overwritten. * * @return true if existing source files should be prompted before being * overwritten */ boolean promptForOverwrite() { return _promptForOverwrite; } //-- promptForOverwrite /** * Sets whether or not existing source files should be silently overwritten * or whether the user should be prompted first. * * @param promptForOverwrite true if existing files should not be silently * overwritten. */ void setPromptForOverwrite(final boolean promptForOverwrite) { this._promptForOverwrite = promptForOverwrite; } //-- setPromptForOverwrite /** * Returns a reference to the schema for which we are generating source. * @return a reference to the schema for which we are generating source. */ Schema getSchema() { return _schema; } //-- getSchema /** * Returns the SourceGenerator instance being used. * @return the SourceGenerator instance being used. */ public SourceGenerator getSourceGenerator() { return _sgen; } //-- getSourceGenerator /** * Returns true if non-fatal warnings should be suppressed. * @return true if non-fatal warnings should be suppressed. */ public boolean getSuppressNonFatalWarnings() { return _suppressNonFatalWarnings; } /** * Sets whether non-fatal warnings should be supporessed. * @param suppressNonFatalWarnings true if non-fatal warnings should be supporessed */ void setSuppressNonFatalWarnings(final boolean suppressNonFatalWarnings) { _suppressNonFatalWarnings = suppressNonFatalWarnings; } /** * Sets the CDR (ClassDescriptorResolver) file associated with the given * filename. * * @param filename the filename associated with the CDR file * @param props the Properties file */ public void setCDRFile(final String filename, final Properties props) { if (filename == null) { String err = "The argument 'filename' must not be null."; throw new IllegalArgumentException(err); } if (_packageListings == null) { _packageListings = new Hashtable<String, Properties>(); } if (props == null) { _packageListings.remove(filename); } else { _packageListings.put(filename, props); } } //-- setCDRFile /** * Sets the Mapping file associated with the given filename. * * @param filename the filename associated with the Mapping * @param mapping the MappingRoot */ public void setMapping(final String filename, final MappingRoot mapping) { if (filename == null) { String err = "The argument 'filename' must not be null."; throw new IllegalArgumentException(err); } if (_mappings == null) { _mappings = new Hashtable<String, MappingRoot>(); } if (mapping == null) { _mappings.remove(filename); } else { _mappings.put(filename, mapping); } } //-- setMapping /** * Returns the Dialog used for interacting with the user. * * @return the Dialog, or null if none has been set. */ public Dialog getDialog() { return _dialog; } //-- getConsoleDialog /** * Sets the Dialog used for interacting with the user. * * @param dialog the Dialog to use */ void setDialog(final Dialog dialog) { _dialog = dialog; } //-- setDialog // /** // * Sets the XMLBindingComponent that this SGStateInfo is working on. // */ // void setXMLBindingComponent(XMLBindingComponent compo) { // _bindingComponent = compo; // } // // /** // * Returns the XMLBindingComponent this SGStateInfo is working on. // * // * @return the XMLBindingComponent this SGStateInfo is working on. // */ // XMLBindingComponent getXMLBindingComponent() { // return _bindingComponent; // } /** * Sets the current status code to the given one. * * @param status the new status code */ public void setStatusCode(final int status) { _status = status; } //-- setStatusCode /** * Sets whether or not the source code generator prints additional messages * during generating source code. * * @param verbose a boolean, when true indicates to print additional * messages */ void setVerbose(final boolean verbose) { this._verbose = verbose; } //-- setVerbose /** * Returns the value of the verbose flag. A true value indicates that * additional messages may be printed during processing. * * @return the value of the verbose flag. */ public boolean verbose() { return this._verbose; } //-- verbose /** * Returns the current FactoryState that holds information about the classes * being generated. * * @return the current FactoryState */ public FactoryState getCurrentFactoryState() { return _currentFactoryState; } /** * Sets the current FactoryState. * @param state the current FactoryState * @see #getCurrentFactoryState */ public void setCurrentFactoryState(final FactoryState state) { _currentFactoryState = state; } // protected JClass getJClass(String name) { // if (name == null) return null; // JClass jClass = (JClass)classTypes.get(name); // // if (jClass == null) { // jClass = new JClass(name); // classTypes.put(name, jClass); // } // return jClass; // } /** * Returns the sources as generated through XML schema imports. * @return the sources as generated through XML schema imports. */ public Map<String, JClass> getImportedSourcesByName() { return _importedSourcesByName; } /** * Returns the sources as generated through XML schema imports. * @return the sources as generated through XML schema imports. */ public Map<String, JClass> getSourcesByName() { return _sourcesByName; } } //-- SGStateInfo