package org.codehaus.modello.core; /* * Copyright (c) 2004, Codehaus.org * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import org.codehaus.modello.ModelloException; import org.codehaus.modello.ModelloRuntimeException; import org.codehaus.modello.core.io.ModelReader; import org.codehaus.modello.metadata.AssociationMetadata; import org.codehaus.modello.metadata.ClassMetadata; import org.codehaus.modello.metadata.FieldMetadata; import org.codehaus.modello.metadata.InterfaceMetadata; import org.codehaus.modello.metadata.MetadataPlugin; import org.codehaus.modello.metadata.ModelMetadata; import org.codehaus.modello.model.CodeSegment; import org.codehaus.modello.model.Model; import org.codehaus.modello.model.ModelAssociation; import org.codehaus.modello.model.ModelClass; import org.codehaus.modello.model.ModelDefault; import org.codehaus.modello.model.ModelField; import org.codehaus.modello.model.ModelInterface; import org.codehaus.modello.model.ModelValidationException; import org.codehaus.modello.plugin.ModelloGenerator; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.ReaderFactory; import java.io.File; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Properties; /** * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a> * @author <a href="mailto:evenisse@codehaus.org">Emmanuel Venisse</a> */ public class DefaultModelloCore extends AbstractModelloCore { /** * @requirement */ private MetadataPluginManager metadataPluginManager; /** * @requirement */ private GeneratorPluginManager generatorPluginManager; public MetadataPluginManager getMetadataPluginManager() { return metadataPluginManager; } public Model loadModel( File file ) throws IOException, ModelloException, ModelValidationException { Reader reader = null; try { reader = ReaderFactory.newXmlReader( file ); return loadModel( reader ); } finally { IOUtil.close( reader ); } } private void upgradeModifiedAttribute( String name, Map<String, String> from, String newName, Map<String, String> to, String warn ) { String value = from.remove( name ); if ( value != null ) { getLogger().warn( warn ); to.put( newName, value ); } } private void upgradeModifiedAttribute( String name, Map<String, String> from, Map<String, String> to, String warn ) { upgradeModifiedAttribute( name, from, name, to, warn ); } private void upgradeModelloModel( ModelReader modelReader, Model model ) { Map<String, String> modelAttributes = modelReader.getAttributesForModel(); upgradeModifiedAttribute( "xsd.target-namespace", modelAttributes, "xsd.targetNamespace", modelAttributes, "attribute 'xsd.target-namespace' for model element is deprecated: " + "it has been renamed to 'xsd.targetNamespace'" ); for ( ModelClass clazz : model.getAllClasses() ) { Map<String, String> classAttributes = modelReader.getAttributesForClass( clazz ); // attributes moved from root class to model upgradeModifiedAttribute( "xml.namespace", classAttributes, modelAttributes, "attribute 'xml.namespace' for class element is deprecated: it should be moved to model element" ); upgradeModifiedAttribute( "xml.schemaLocation", classAttributes, modelAttributes, "attribute 'xml.schemaLocation' for class element is deprecated: it should be moved to model element" ); for ( ModelField field : clazz.getAllFields() ) { if ( field instanceof ModelAssociation ) { Map<String, String> fieldAttributes = modelReader.getAttributesForField( field ); Map<String, String> associationAttributes = modelReader.getAttributesForAssociation( (ModelAssociation)field ); upgradeModifiedAttribute( "java.adder", fieldAttributes, associationAttributes, "attribute 'java.adder' for field element is deprecated: it should be moved to association" ); upgradeModifiedAttribute( "java.generate-create", associationAttributes, "java.bidi", associationAttributes, "attribute 'java.generate-create' for association " + "element is deprecated: it has been renamed to 'java.bidi'" ); upgradeModifiedAttribute( "java.generate-break", associationAttributes, "java.bidi", associationAttributes, "attribute 'java.generate-break' for association " + "element is deprecated: it has been renamed to 'java.bidi'" ); upgradeModifiedAttribute( "java.use-interface", associationAttributes, "java.useInterface", associationAttributes, "attribute 'xml.use-interface' for association " + "element is deprecated: it has been renamed to 'xml.useInterface'" ); upgradeModifiedAttribute( "xml.associationTagName", fieldAttributes, "xml.tagName", associationAttributes, "attribute 'xml.associationTagName' for field element is " + "deprecated: use 'xml.tagName' in association instead" ); upgradeModifiedAttribute( "xml.listStyle", fieldAttributes, "xml.itemsStyle", associationAttributes, "attribute 'xml.listStyle' for field element is " + "deprecated: use 'xml.itemsStyle' in association instead" ); } if ( "Content".equals( field.getType() ) ) { getLogger().warn( "'Content' type is deprecated: use 'String' type and add xml.content='true' to the field" ); field.setType( "String" ); Map<String, String> fieldAttributes = modelReader.getAttributesForField( field ); fieldAttributes.put( "xml.content", "true" ); } } } } public Model loadModel( Reader reader ) throws ModelloException, ModelValidationException { ModelReader modelReader = new ModelReader(); Model model = modelReader.loadModel( reader ); model.initialize(); // keep backward compatibility with Modello attributes model changes upgradeModelloModel( modelReader, model ); handlePluginsMetadata( modelReader, model ); validate( model ); return model; } /** * Handle Plugins Metadata. * * @throws ModelloException */ private void handlePluginsMetadata( ModelReader modelReader, Model model ) throws ModelloException { Collection<MetadataPlugin> plugins = metadataPluginManager.getPlugins().values(); for ( MetadataPlugin plugin : plugins ) { Map<String, String> attributes = modelReader.getAttributesForModel(); attributes = Collections.unmodifiableMap( attributes ); ModelMetadata metadata = plugin.getModelMetadata( model, attributes ); if ( metadata == null ) { throw new ModelloException( "A meta data plugin must not return null." ); } model.addMetadata( metadata ); } for ( ModelClass clazz : model.getAllClasses() ) { Map<String, String> attributes = modelReader.getAttributesForClass( clazz ); attributes = Collections.unmodifiableMap( attributes ); for ( MetadataPlugin plugin : plugins ) { ClassMetadata metadata = plugin.getClassMetadata( clazz, attributes ); if ( metadata == null ) { throw new ModelloException( "A meta data plugin must not return null." ); } clazz.addMetadata( metadata ); } for ( ModelField field : clazz.getAllFields() ) { if ( field instanceof ModelAssociation ) { ModelAssociation modelAssociation = (ModelAssociation) field; Map<String, String> fieldAttributes = modelReader.getAttributesForField( modelAssociation ); fieldAttributes = Collections.unmodifiableMap( fieldAttributes ); Map<String, String> associationAttributes = modelReader.getAttributesForAssociation( modelAssociation ); associationAttributes = Collections.unmodifiableMap( associationAttributes ); for ( MetadataPlugin plugin : plugins ) { FieldMetadata fieldMetadata = plugin.getFieldMetadata( modelAssociation, fieldAttributes ); if ( fieldMetadata == null ) { throw new ModelloException( "A meta data plugin must not return null." ); } modelAssociation.addMetadata( fieldMetadata ); AssociationMetadata associationMetadata = plugin.getAssociationMetadata( modelAssociation, associationAttributes ); if ( associationMetadata == null ) { throw new ModelloException( "A meta data plugin must not return null." ); } modelAssociation.addMetadata( associationMetadata ); } } else { attributes = modelReader.getAttributesForField( field ); attributes = Collections.unmodifiableMap( attributes ); for ( MetadataPlugin plugin : plugins ) { FieldMetadata metadata = plugin.getFieldMetadata( field, attributes ); if ( metadata == null ) { throw new ModelloException( "A meta data plugin must not return null." ); } field.addMetadata( metadata ); } } } } for ( ModelInterface iface : model.getAllInterfaces() ) { Map<String, String> attributes = modelReader.getAttributesForInterface( iface ); attributes = Collections.unmodifiableMap( attributes ); for ( MetadataPlugin plugin : plugins ) { InterfaceMetadata metadata = plugin.getInterfaceMetadata( iface, attributes ); if ( metadata == null ) { throw new ModelloException( "A meta data plugin must not return null." ); } iface.addMetadata( metadata ); } } } /** * Validate the entire model. * * @throws ModelValidationException */ private void validate( Model model ) throws ModelValidationException { model.validate(); for ( ModelDefault modelDefault : model.getDefaults() ) { modelDefault.validateElement(); } for ( ModelClass modelClass : model.getAllClasses() ) { modelClass.validate(); } for ( ModelClass modelClass : model.getAllClasses() ) { for ( ModelField field : modelClass.getAllFields() ) { field.validate(); } for ( CodeSegment codeSegment : modelClass.getAllCodeSegments() ) { codeSegment.validate(); } } } public void saveModel( Model model, Writer writer ) throws ModelloException { throw new ModelloRuntimeException( "Not implemented." ); } public Model translate( Reader reader, String inputType, Properties parameters ) throws ModelloException { throw new ModelloRuntimeException( "Not implemented." ); } public void generate( Model model, String outputType, Properties parameters ) throws ModelloException { if ( model == null ) { throw new ModelloRuntimeException( "Illegal argument: model == null." ); } if ( outputType == null ) { throw new ModelloRuntimeException( "Illegal argument: outputType == null." ); } if ( parameters == null ) { parameters = new Properties(); } ModelloGenerator generator = generatorPluginManager.getGeneratorPlugin( outputType ); generator.generate( model, parameters ); } }