From: Chad B. <cwb...@us...> - 2004-06-20 03:48:31
|
User: cwbrandon Date: 04/06/19 20:48:23 Modified: src/java/org/andromda/core/anttasks AndroMDAGenTask.java RepositoryConfiguration.java src/java/org/andromda/core/metafacade MetafacadeBase.java MetafacadeFactory.java src/java/org/andromda/core/repository RepositoryFacade.java Added: src/java/org/andromda/core ModelProcessorException.java ModelProcessor.java Model.java src/java/org/andromda/core/metafacade ModelValidationMessage.java Log: - Abstract out the processing of models into a generic ModelProcessor class from which the AndroMDAGenTask now just wraps, now the framework isn't so tied to just ant, this allows people to programmatically call andromda through other means as well. - At the same time add the ability to list all validation errors at the end of model processing. - Cleanup/add javadocs Revision Changes Path 1.1 andromda/src/java/org/andromda/core/ModelProcessorException.java Index: ModelProcessorException.java =================================================================== package org.andromda.core; /** * Any unchecked exception that will be thrown during * the execution of the ModelProcessor */ public class ModelProcessorException extends RuntimeException { /** * Constructs an instance of ModelProcessorException. * * @param th */ public ModelProcessorException(Throwable th){ super(th); } /** * Constructs an instance of ModelProcessorException. * * @param msg */ public ModelProcessorException(String msg) { super(msg); } /** * Constructs an instance of ModelProcessorException. * * @param msg * @param th */ public ModelProcessorException(String msg, Throwable th) { super(msg, th); } } 1.1 andromda/src/java/org/andromda/core/ModelProcessor.java Index: ModelProcessor.java =================================================================== package org.andromda.core; import java.util.Collection; import java.util.Iterator; import org.andromda.core.cartridge.Cartridge; import org.andromda.core.common.CodeGenerationContext; import org.andromda.core.common.ComponentContainer; import org.andromda.core.common.ExceptionUtils; import org.andromda.core.common.Namespace; import org.andromda.core.common.Namespaces; import org.andromda.core.common.PluginDiscoverer; import org.andromda.core.common.StdoutLogger; import org.andromda.core.metafacade.MetafacadeFactory; import org.andromda.core.metafacade.ModelValidationMessage; import org.andromda.core.repository.RepositoryFacade; import org.apache.log4j.Logger; /** * <p> * The main entry point to the framework, handles the loading/processing of * models by plugins. Facilitates Model Driven Architecture by enabling the * generation of source code, configuration files, and other such artifacts from * a single or multiple <code>MOF</code> models. * </p> * * @author <a href="http://www.mbohlen.de">Matthias Bohlen </a> * @author <A HREF="http://www.amowers.com">Anthony Mowers </A> * @author Chad Brandon */ public class ModelProcessor { private static final Logger logger = Logger.getLogger(ModelProcessor.class); private static ModelProcessor instance = null; /** * Gets the shared instance of the ModelProcessor. * * @return the shared ModelProcessor instance. */ public static ModelProcessor instance() { if (instance == null) { instance = new ModelProcessor(); } return instance; } /** * Processes all <code>models</code> with the given * <code>cartridges</code>. * * @param models an array of URLs to models. * @param cartridges the Cartridge instances to process with. */ public void process(Model[] models) { final String methodName = "ModelProcessor.process"; ExceptionUtils.checkNull(methodName, "models", models); long startTime = System.currentTimeMillis(); try { PluginDiscoverer.instance().discoverPlugins(); Collection cartridges = PluginDiscoverer.instance().findPlugins( Cartridge.class); if (cartridges.size() <= 0) { StdoutLogger .warn("WARNING! No cartridges found, check your classpath!"); } RepositoryFacade repository = (RepositoryFacade)ComponentContainer .instance().findComponent(RepositoryFacade.class); if (repository == null) { throw new ModelProcessorException( "No Repository could be found, " + "please make sure you have a " + RepositoryFacade.class.getName() + " instance on your classpath"); } repository.open(); if (models != null && cartridges != null) { for (int ctr = 0; ctr < models.length; ctr++) { process(repository, models[ctr], cartridges); } } repository.close(); repository = null; } finally { // log all the error messages Collection messages = MetafacadeFactory.getInstance() .getValidationMessages(); if (messages != null && !messages.isEmpty()) { Logger validationLogger = Logger.getLogger("VALIDATION:ERROR"); Iterator messageIt = messages.iterator(); while (messageIt.hasNext()) { ModelValidationMessage message = (ModelValidationMessage)messageIt .next(); validationLogger.error(message); } } StdoutLogger.info("completed model processing, TIME --> " + ((System.currentTimeMillis() - startTime) / 1000.0) + "[s]"); } } /** * Processes a single <code>model</code> * * @param repository the RepositoryFacade that will be used to read/load the * model * @param model the Model to process. */ private void process( RepositoryFacade repository, Model model, Collection cartridges) { final String methodName = "ModelProcessor.process"; try { //-- command line status StdoutLogger.info("Input model --> '" + model.getUrl() + "'"); repository.readModel(model.getUrl(), model.getModuleSearchPath()); CodeGenerationContext context = new CodeGenerationContext( repository, model.isLastModifiedCheck(), model.getPackages()); Namespace defaultNamespace = Namespaces.instance().findNamespace( Namespaces.DEFAULT); for (Iterator cartridgeIt = cartridges.iterator(); cartridgeIt .hasNext();) { Cartridge cartridge = (Cartridge)cartridgeIt.next(); String cartridgeName = cartridge.getName(); Namespace namespace = Namespaces.instance().findNamespace( cartridgeName); boolean ignoreNamespace = false; if (namespace != null) { ignoreNamespace = namespace.isIgnore(); } // make sure we ignore the cartridge if the namespace // is set to 'ignore' if ((namespace != null || defaultNamespace != null) && !ignoreNamespace) { cartridge.init(); cartridge.processModelElements(context); cartridge.shutdown(); } else { StdoutLogger .info("namespace for '" + cartridgeName + "' cartridge is either not defined, or has the ignore " + "attribute set to 'true' --> skipping processing"); } } } catch (Throwable th) { String errMsg = "Error performing " + methodName + " with model --> '" + model.getUrl() + "'"; logger.error(errMsg, th); throw new ModelProcessorException(errMsg, th); } } } 1.1 andromda/src/java/org/andromda/core/Model.java Index: Model.java =================================================================== package org.andromda.core; import java.net.URL; import org.andromda.core.common.ModelPackages; /** * Stores the processing information for each model * that AndroMDA will process. * * @author Chad Brandon */ public class Model { /** * The URL of the model. */ private URL url; /** * Stores the information about what packages should/shouldn't be processed. */ private ModelPackages packages = new ModelPackages(); /** * Whether or not to perform a last modified check on the model. */ private boolean lastModifiedCheck; /** * The path to search for the model's <em>modules</em> (i.e. models that * are referenced as HREF <code>modules</code> from within this model) */ private String[] moduleSearchPath; /** * Constructs a new instance of this Model * * @param url the URL to the model to process. * @param lastModifiedCheck whether or not to perform a last modified check * when processing the model. If <code>true</code> the model will * be checked for a timestamp before processing occurs. * @param packages the packages to include/ignore when processing the model. * @param moduleSearchPath any array of path's to search for any HREF * modules (profile, etc) referenced from within ths model. */ public Model( URL url, ModelPackages packages, boolean lastModifiedCheck, String[] moduleSearchPath) { this.lastModifiedCheck = lastModifiedCheck; this.url = url; this.packages = packages; } /** * @return Returns the lastModifiedCheck. */ public boolean isLastModifiedCheck() { return lastModifiedCheck; } /** * @return Returns the packages. */ public ModelPackages getPackages() { return packages; } /** * @return Returns the url. */ public URL getUrl() { return url; } /** * Gets the path to search for the model's <em>modules</em> (i.e. models * that are referenced as HREF <code>modules</code> from within this * model). Will be null if the path isn't specified. * * @return Returns the moduleSearchPath. */ public String[] getModuleSearchPath() { return moduleSearchPath; } } 1.37 +42 -114 andromda/src/java/org/andromda/core/anttasks/AndroMDAGenTask.java Index: AndroMDAGenTask.java =================================================================== RCS file: /cvsroot/andromda/andromda/src/java/org/andromda/core/anttasks/AndroMDAGenTask.java,v retrieving revision 1.36 retrieving revision 1.37 diff -u -w -r1.36 -r1.37 --- AndroMDAGenTask.java 10 Jun 2004 12:40:53 -0000 1.36 +++ AndroMDAGenTask.java 20 Jun 2004 03:48:22 -0000 1.37 @@ -7,6 +7,8 @@ import java.util.Collection; import java.util.Iterator; +import org.andromda.core.Model; +import org.andromda.core.ModelProcessor; import org.andromda.core.cartridge.Cartridge; import org.andromda.core.common.CodeGenerationContext; import org.andromda.core.common.ExceptionUtils; @@ -24,12 +26,13 @@ import org.apache.tools.ant.taskdefs.MatchingTask; /** - * This class represents the <code><andromda></code> custom task which can - * be called from an ant script. + * <p> + * This class wraps the AndroMDA model processor so that AndroMDA can be used as an Ant task. + * Represents the <code><andromda></code> custom task which can be called from an Ant + * build script. + * </p> * - * The <andromda> task facilitates Model Driven Architecture by enabling - * the generation of source code, configuration files, and other such artifacts - * from a MOF model. + * @see org.andromda.core.ModelProcessor * * @author <a href="http://www.mbohlen.de">Matthias Bohlen</a> * @author <A HREF="http://www.amowers.com">Anthony Mowers</A> @@ -125,10 +128,10 @@ /** * <p> - * * Turns on/off last modified checking for generated files. If checking is * turned on, overwritable files are regenerated only when the model is newer - * than the file to be generated. By default, it is on.</p> + * than the file to be generated. By default, it is on. + * </p> * *@param lastmod set the modified check, yes or no? */ @@ -139,11 +142,14 @@ /** * <p> - * * Starts the generation of source code from an object model. + * </p> * - * This is the main entry point of the application. It is called by ant whenever - * the surrounding task is executed (which could be multiple times).</p> + * <p> + * This is the main entry point of the application when running Ant. + * It is called by ant whenever the surrounding task is executed + * (which could be multiple times). + * </p> * *@throws BuildException if something goes wrong */ @@ -151,8 +157,6 @@ { try { - long startTime = System.currentTimeMillis(); - this.initNamespaces(); DirectoryScanner scanner; @@ -165,23 +169,21 @@ baseDir = this.getProject().resolveFile("."); } - PluginDiscoverer.instance().discoverPlugins(); - - Collection cartridges = - PluginDiscoverer.instance().findPlugins(Cartridge.class); - - if (cartridges.size() <= 0) - { - StdoutLogger.warn( - "WARNING! No cartridges found, check your classpath!"); - } - - createRepository().createRepository().open(); + String[] moduleSearchPath = + this.createRepository().createModuleSearchPath().list(); + Model[] models; + // if the modelURL is specified explicitly + // then we just set models as the one model if (modelURL != null) { - // process the model via the explicit modelURL - process(modelURL, cartridges); + models = new Model[] { + new Model( + modelURL, + this.packages, + this.lastModifiedCheck, + moduleSearchPath) + }; } else { @@ -193,20 +195,22 @@ if (list.length > 0) { - for (int i = 0; i < list.length; ++i) + models = new Model[list.length]; + for (int ctr = 0; ctr < list.length; ++ctr) { - URL url = null; - File inFile = new File(baseDir, list[i]); - + File inFile = new File(baseDir, list[ctr]); try { - url = inFile.toURL(); - process(url, cartridges); + models[ctr] = new Model( + inFile.toURL(), + this.packages, + this.lastModifiedCheck, + moduleSearchPath); } catch (MalformedURLException mfe) { throw new BuildException( - "Malformed model URI --> '" + url + "'"); + "Malformed model URI --> '" + inFile + "'"); } } } @@ -216,12 +220,8 @@ } } - createRepository().createRepository().close(); - StdoutLogger.info( - "completed model processing, TIME --> " - + ((System.currentTimeMillis() - startTime) / 1000.0) - + "[s]"); - + // pass the loaded model(s) to the ModelProcessor + ModelProcessor.instance().process(models); } finally { @@ -233,78 +233,6 @@ } } - private void process(URL url, Collection cartridges) throws BuildException - { - final String methodName = "AndroMDAGenTask.process"; - ExceptionUtils.checkNull(methodName, "url", url); - - CodeGenerationContext context = null; - - try - { - //-- command line status - StdoutLogger.info("Input model --> '" + url + "'"); - - // configure repository - RepositoryConfiguration rc = createRepository(); - RepositoryFacade repository = rc.createRepository(); - repository.open(); - repository.readModel(url, rc.createModuleSearchPath().list()); - - context = - new CodeGenerationContext( - repository, - lastModifiedCheck, - packages); - - Namespace defaultNamespace = - Namespaces.instance().findNamespace(Namespaces.DEFAULT); - - for (Iterator cartridgeIt = cartridges.iterator(); cartridgeIt.hasNext();) - { - Cartridge cartridge = (Cartridge)cartridgeIt.next(); - - String cartridgeName = - cartridge.getName(); - - Namespace namespace = - Namespaces.instance().findNamespace(cartridgeName); - - boolean ignoreNamespace = false; - if (namespace != null) { - ignoreNamespace = namespace.isIgnore(); - } - - // make sure we ignore the cartridge if the namespace - // is set to 'ignore' - if ((namespace != null || defaultNamespace != null) && !ignoreNamespace) - { - cartridge.init(); - cartridge.processModelElements(context); - cartridge.shutdown(); - } - else - { - StdoutLogger.info("namespace for '" + cartridgeName - + "' cartridge is either not defined, or has the ignore " - + "attribute set to 'true' --> skipping processing"); - } - } - repository.close(); - repository = null; - } - catch (Throwable th) - { - String errMsg = "Error performing " + methodName + - " with model --> '" - + url + "'"; - logger.error(errMsg, th); - throw new BuildException( - errMsg, th); - - } - } - /** * This method would normally be unnecessary. It is here because of a bug in * ant. Ant calls addNamespace() before the Namespace javabean is fully 1.14 +0 -28 andromda/src/java/org/andromda/core/anttasks/RepositoryConfiguration.java Index: RepositoryConfiguration.java =================================================================== RCS file: /cvsroot/andromda/andromda/src/java/org/andromda/core/anttasks/RepositoryConfiguration.java,v retrieving revision 1.13 retrieving revision 1.14 diff -u -w -r1.13 -r1.14 --- RepositoryConfiguration.java 8 Apr 2004 14:49:32 -0000 1.13 +++ RepositoryConfiguration.java 20 Jun 2004 03:48:22 -0000 1.14 @@ -41,34 +41,6 @@ } /** - * Sets the name of the class to use as the repository. The - * class must implement the RepositoryFacade interface. - * - * @see org.andromda.core.repository.RepositoryFacade - * - * @param repositoryClassName - */ - public void setClassname(String repositoryClassName) - { - if (StringUtils.isNotBlank(repositoryClassName)) { - ComponentContainer.instance().registerDefaultComponent( - RepositoryFacade.class, - repositoryClassName); - } - } - - /** - * Creates an instance of the repository. - * - * @return RepositoryFacade - */ - public RepositoryFacade createRepository() - { - return (RepositoryFacade)ComponentContainer.instance().findComponent( - RepositoryFacade.class); - } - - /** * Handles the nested <moduleSearchPath> element. * The user can specify her own search path for submodels * of the models that she is going to process. 1.8 +11 -36 andromda/src/java/org/andromda/core/metafacade/MetafacadeBase.java Index: MetafacadeBase.java =================================================================== RCS file: /cvsroot/andromda/andromda/src/java/org/andromda/core/metafacade/MetafacadeBase.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -w -r1.7 -r1.8 --- MetafacadeBase.java 15 Jun 2004 21:08:33 -0000 1.7 +++ MetafacadeBase.java 20 Jun 2004 03:48:22 -0000 1.8 @@ -55,30 +55,32 @@ * to check whether it is in a valid state. * <p> * In the lifecycle of a model element facade it is validated only once. + * + * @param validationMessages any messages generated during validation. */ - public final void validate() + public final void validate(Collection validationMessages) { - if (!hasBeenValidated) + if (!this.hasBeenValidated) { - hasBeenValidated = true; - __handleInvariants(); + this.hasBeenValidated = true; + this.handleInvariants(validationMessages); } } /** * <p> * The logic of modeled OCL invariants from derived metafacades - * will be generated into this method which is then called by - * #validate(). + * will be generated into this method and validation messages + * created and collected into the <code>messages</code> collection. + * This method is called by validate #validate(). * <p> * * <p> * By default this method is empty. * </p> */ - protected void __handleInvariants() - { - } + protected void handleInvariants(Collection messages) + {} /** * Returns a collection of facades for a collection @@ -287,31 +289,4 @@ { logger = l; } - - /** - * This method handles a validation error. - * <p> - * From an error cannot be recovered, if the user chooses to continue working with - * the result he will most probably experience undefined behavior. - * - * @param error The error message - */ - protected void validationError(String error) - { - logger.error("[error] " + metaObject + " : " + error); - } - - /** - * This method handles a validation warning. - * <p> - * A warning denotes an issue that can be corrected by the facade itself, although - * it is be advisable the user corrects this issue because of a more pleasing end-result. - * - * @param warning The warning message - */ - protected void validationWarning(String warning) - { - logger.warn("[warning] " + metaObject + " : " + warning); - } - } 1.8 +23 -6 andromda/src/java/org/andromda/core/metafacade/MetafacadeFactory.java Index: MetafacadeFactory.java =================================================================== RCS file: /cvsroot/andromda/andromda/src/java/org/andromda/core/metafacade/MetafacadeFactory.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -w -r1.7 -r1.8 --- MetafacadeFactory.java 10 Jun 2004 03:19:13 -0000 1.7 +++ MetafacadeFactory.java 20 Jun 2004 03:48:23 -0000 1.8 @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -30,6 +31,11 @@ private ModelAccessFacade model; /** + * Any validation messages stored during processing. + */ + private Collection validationMessages; + + /** * The cache for already created metafacades. */ private Map metafacadeCache; @@ -45,6 +51,7 @@ { this.metafacadeCache = new HashMap(); this.registeredProperties = new HashMap(); + this.validationMessages = new HashSet(); MetafacadeMappings.instance().discoverMetafacades(); MetafacadeImpls.instance().discoverMetafacadeImpls(); } @@ -158,7 +165,6 @@ if (metafacadeClass == null) { - if (mapping != null) { metafacadeClass = mapping.getMetafacadeClass(); @@ -248,9 +254,10 @@ metafacade, mapping.getPropertyReferences()); } - // validate the meta-facade - metafacade.validate(); - + // validate the meta-facade and collect the messages + Collection validationMessages = new ArrayList(); + metafacade.validate(validationMessages); + this.validationMessages.addAll(validationMessages); this.addToMetafacadeCache( metaobject, metafacadeCacheKey, @@ -591,4 +598,14 @@ return registeredProperty; } + /** + * Gets the validation messages collection during + * model processing. + * + * @return Returns the validationMessages. + */ + public Collection getValidationMessages() + { + return validationMessages; + } } 1.1 andromda/src/java/org/andromda/core/metafacade/ModelValidationMessage.java Index: ModelValidationMessage.java =================================================================== package org.andromda.core.metafacade; import org.andromda.core.common.ExceptionUtils; import org.apache.log4j.Logger; /** * Stores the validation messages that are stored up to be * output at the end model processing. * * @author Chad Brandon */ public class ModelValidationMessage { /** * Constructs a new instance of MetafacadeValidationMessage * taking the <code>metafacadeClass</code> the * <code>modelElementName</code> and <code>message</code>. * * @param metafacadeClass the Class of the metafacade being validated. * @param modelElementName the name of the model element being validated. * @param message the message to to communitate about the validation. */ public ModelValidationMessage( Class metafacadeClass, String modelElementName, String message) { final String constructorName = "MetafacadeValidationMessage"; ExceptionUtils.checkNull(constructorName, "metafacadeClass", metafacadeClass); ExceptionUtils.checkEmpty(constructorName, "message", message); this.metafacadeClass = metafacadeClass; this.modelElementName = modelElementName; this.message = message; } private Class metafacadeClass; private String modelElementName; private String message; /** * @return Returns the message. */ public String getMessage() { return message; } /** * @return Returns the metafacadeClass. */ public Class getMetafacadeClass() { return metafacadeClass; } /** * @return Returns the modelElementName. */ public String getModelElementName() { return modelElementName; } /** * @see java.lang.Object#toString() */ public String toString() { StringBuffer toString = new StringBuffer(metafacadeClass.getName()); toString.append("["); toString.append(modelElementName); toString.append("]"); toString.append(" :"); toString.append(this.message); return toString.toString(); } } 1.3 +2 -0 andromda/src/java/org/andromda/core/repository/RepositoryFacade.java Index: RepositoryFacade.java =================================================================== RCS file: /cvsroot/andromda/andromda/src/java/org/andromda/core/repository/RepositoryFacade.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -w -r1.2 -r1.3 --- RepositoryFacade.java 26 Mar 2004 08:15:02 -0000 1.2 +++ RepositoryFacade.java 20 Jun 2004 03:48:23 -0000 1.3 @@ -38,6 +38,8 @@ * a file in a jar file, a file from a website, data from a database, etc... </p> * * @param modelURL url of model + * @param moduleSearchPath a list of paths from which to search for + * module models (i.e. models that can be used from within other models). * @throws MetaDataReadException if model syntax is violated * @throws IOException if io error occurs during file read */ |