View Javadoc

1   package org.codehaus.modello.core;
2   
3   /*
4    * Copyright (c) 2004, Codehaus.org
5    *
6    * Permission is hereby granted, free of charge, to any person obtaining a copy of
7    * this software and associated documentation files (the "Software"), to deal in
8    * the Software without restriction, including without limitation the rights to
9    * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10   * of the Software, and to permit persons to whom the Software is furnished to do
11   * so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in all
14   * copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   * SOFTWARE.
23   */
24  
25  import org.codehaus.modello.ModelloException;
26  import org.codehaus.modello.ModelloRuntimeException;
27  import org.codehaus.modello.core.io.ModelReader;
28  import org.codehaus.modello.metadata.AssociationMetadata;
29  import org.codehaus.modello.metadata.ClassMetadata;
30  import org.codehaus.modello.metadata.FieldMetadata;
31  import org.codehaus.modello.metadata.InterfaceMetadata;
32  import org.codehaus.modello.metadata.MetadataPlugin;
33  import org.codehaus.modello.metadata.ModelMetadata;
34  import org.codehaus.modello.model.CodeSegment;
35  import org.codehaus.modello.model.Model;
36  import org.codehaus.modello.model.ModelAssociation;
37  import org.codehaus.modello.model.ModelClass;
38  import org.codehaus.modello.model.ModelDefault;
39  import org.codehaus.modello.model.ModelField;
40  import org.codehaus.modello.model.ModelInterface;
41  import org.codehaus.modello.model.ModelValidationException;
42  import org.codehaus.modello.plugin.ModelloGenerator;
43  import org.codehaus.plexus.util.IOUtil;
44  import org.codehaus.plexus.util.ReaderFactory;
45  
46  import java.io.File;
47  import java.io.IOException;
48  import java.io.Reader;
49  import java.io.Writer;
50  import java.util.Collection;
51  import java.util.Collections;
52  import java.util.Map;
53  import java.util.Properties;
54  
55  /**
56   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
57   * @author <a href="mailto:evenisse@codehaus.org">Emmanuel Venisse</a>
58   */
59  public class DefaultModelloCore
60      extends AbstractModelloCore
61  {
62      /**
63       * @requirement
64       */
65      private MetadataPluginManager metadataPluginManager;
66  
67      /**
68       * @requirement
69       */
70      private GeneratorPluginManager generatorPluginManager;
71  
72      public MetadataPluginManager getMetadataPluginManager()
73      {
74          return metadataPluginManager;
75      }
76  
77      public Model loadModel( File file )
78          throws IOException, ModelloException, ModelValidationException
79      {
80          Reader reader = null;
81  
82          try
83          {
84              reader = ReaderFactory.newXmlReader( file );
85              return loadModel( reader );
86          }
87          finally
88          {
89              IOUtil.close( reader );
90          }
91      }
92  
93      private void upgradeModifiedAttribute( String name, Map<String, String> from, String newName,
94                                             Map<String, String> to, String warn )
95      {
96          String value = from.remove( name );
97  
98          if ( value != null )
99          {
100             getLogger().warn( warn );
101 
102             to.put( newName, value );
103         }
104     }
105 
106     private void upgradeModifiedAttribute( String name, Map<String, String> from, Map<String, String> to, String warn )
107     {
108         upgradeModifiedAttribute( name, from, name, to, warn );
109     }
110 
111     private void upgradeModelloModel( ModelReader modelReader, Model model )
112     {
113         Map<String, String> modelAttributes = modelReader.getAttributesForModel();
114 
115         upgradeModifiedAttribute( "xsd.target-namespace", modelAttributes, "xsd.targetNamespace", modelAttributes,
116                                   "attribute 'xsd.target-namespace' for model element is deprecated: "
117                                   + "it has been renamed to 'xsd.targetNamespace'" );
118 
119         for ( ModelClass clazz : model.getAllClasses() )
120         {
121             Map<String, String> classAttributes = modelReader.getAttributesForClass( clazz );
122 
123             // attributes moved from root class to model
124             upgradeModifiedAttribute( "xml.namespace", classAttributes, modelAttributes,
125                 "attribute 'xml.namespace' for class element is deprecated: it should be moved to model element" );
126 
127             upgradeModifiedAttribute( "xml.schemaLocation", classAttributes, modelAttributes,
128                 "attribute 'xml.schemaLocation' for class element is deprecated: it should be moved to model element" );
129 
130             for ( ModelField field : clazz.getAllFields() )
131             {
132                 if ( field instanceof ModelAssociation )
133                 {
134                     Map<String, String> fieldAttributes = modelReader.getAttributesForField( field );
135                     Map<String, String> associationAttributes = modelReader.getAttributesForAssociation( (ModelAssociation)field );
136 
137                     upgradeModifiedAttribute( "java.adder", fieldAttributes, associationAttributes,
138                         "attribute 'java.adder' for field element is deprecated: it should be moved to association" );
139 
140                     upgradeModifiedAttribute( "java.generate-create", associationAttributes,
141                         "java.bidi", associationAttributes, "attribute 'java.generate-create' for association "
142                         + "element is deprecated: it has been renamed to 'java.bidi'" );
143 
144                     upgradeModifiedAttribute( "java.generate-break", associationAttributes,
145                         "java.bidi", associationAttributes, "attribute 'java.generate-break' for association "
146                         + "element is deprecated: it has been renamed to 'java.bidi'" );
147 
148                     upgradeModifiedAttribute( "java.use-interface", associationAttributes,
149                         "java.useInterface", associationAttributes, "attribute 'xml.use-interface' for association "
150                         + "element is deprecated: it has been renamed to 'xml.useInterface'" );
151 
152                     upgradeModifiedAttribute( "xml.associationTagName", fieldAttributes,
153                         "xml.tagName", associationAttributes, "attribute 'xml.associationTagName' for field element is "
154                         + "deprecated: use 'xml.tagName' in association instead" );
155 
156                     upgradeModifiedAttribute( "xml.listStyle", fieldAttributes,
157                         "xml.itemsStyle", associationAttributes, "attribute 'xml.listStyle' for field element is "
158                         + "deprecated: use 'xml.itemsStyle' in association instead" );
159                 }
160 
161                 if ( "Content".equals( field.getType() ) )
162                 {
163                     getLogger().warn( "'Content' type is deprecated: use 'String' type and add xml.content='true' to the field" );
164                     field.setType( "String" );
165                     Map<String, String> fieldAttributes = modelReader.getAttributesForField( field );
166                     fieldAttributes.put( "xml.content", "true" );
167                 }
168             }
169         }
170     }
171 
172     public Model loadModel( Reader reader )
173         throws ModelloException, ModelValidationException
174     {
175         ModelReader modelReader = new ModelReader();
176         Model model = modelReader.loadModel( reader );
177 
178         model.initialize();
179 
180         // keep backward compatibility with Modello attributes model changes
181         upgradeModelloModel( modelReader, model );
182 
183         handlePluginsMetadata( modelReader, model );
184 
185         validate( model );
186 
187         return model;
188     }
189 
190     /**
191      * Handle Plugins Metadata.
192      *
193      * @throws ModelloException
194      */
195     private void handlePluginsMetadata( ModelReader modelReader, Model model )
196         throws ModelloException
197     {
198         Collection<MetadataPlugin> plugins = metadataPluginManager.getPlugins().values();
199 
200         for ( MetadataPlugin plugin : plugins )
201         {
202             Map<String, String> attributes = modelReader.getAttributesForModel();
203 
204             attributes = Collections.unmodifiableMap( attributes );
205 
206             ModelMetadata metadata = plugin.getModelMetadata( model, attributes );
207 
208             if ( metadata == null )
209             {
210                 throw new ModelloException( "A meta data plugin must not return null." );
211             }
212 
213             model.addMetadata( metadata );
214         }
215 
216         for ( ModelClass clazz : model.getAllClasses() )
217         {
218             Map<String, String> attributes = modelReader.getAttributesForClass( clazz );
219 
220             attributes = Collections.unmodifiableMap( attributes );
221 
222             for ( MetadataPlugin plugin : plugins )
223             {
224                 ClassMetadata metadata = plugin.getClassMetadata( clazz, attributes );
225 
226                 if ( metadata == null )
227                 {
228                     throw new ModelloException( "A meta data plugin must not return null." );
229                 }
230 
231                 clazz.addMetadata( metadata );
232             }
233 
234             for ( ModelField field : clazz.getAllFields() )
235             {
236                 if ( field instanceof ModelAssociation )
237                 {
238                     ModelAssociation modelAssociation = (ModelAssociation) field;
239 
240                     Map<String, String> fieldAttributes = modelReader.getAttributesForField( modelAssociation );
241 
242                     fieldAttributes = Collections.unmodifiableMap( fieldAttributes );
243 
244                     Map<String, String> associationAttributes = modelReader.getAttributesForAssociation( modelAssociation );
245 
246                     associationAttributes = Collections.unmodifiableMap( associationAttributes );
247 
248                     for ( MetadataPlugin plugin : plugins )
249                     {
250                         FieldMetadata fieldMetadata = plugin.getFieldMetadata( modelAssociation, fieldAttributes );
251 
252                         if ( fieldMetadata == null )
253                         {
254                             throw new ModelloException( "A meta data plugin must not return null." );
255                         }
256 
257                         modelAssociation.addMetadata( fieldMetadata );
258 
259                         AssociationMetadata associationMetadata = plugin.getAssociationMetadata( modelAssociation, associationAttributes );
260 
261                         if ( associationMetadata == null )
262                         {
263                             throw new ModelloException( "A meta data plugin must not return null." );
264                         }
265 
266                         modelAssociation.addMetadata( associationMetadata );
267                     }
268                 }
269                 else
270                 {
271                     attributes = modelReader.getAttributesForField( field );
272 
273                     attributes = Collections.unmodifiableMap( attributes );
274 
275                     for ( MetadataPlugin plugin : plugins )
276                     {
277                         FieldMetadata metadata = plugin.getFieldMetadata( field, attributes );
278 
279                         if ( metadata == null )
280                         {
281                             throw new ModelloException( "A meta data plugin must not return null." );
282                         }
283 
284                         field.addMetadata( metadata );
285                     }
286                 }
287             }
288         }
289 
290         for ( ModelInterface iface : model.getAllInterfaces() )
291         {
292             Map<String, String> attributes = modelReader.getAttributesForInterface( iface );
293 
294             attributes = Collections.unmodifiableMap( attributes );
295 
296             for ( MetadataPlugin plugin : plugins )
297             {
298                 InterfaceMetadata metadata = plugin.getInterfaceMetadata( iface, attributes );
299 
300                 if ( metadata == null )
301                 {
302                     throw new ModelloException( "A meta data plugin must not return null." );
303                 }
304 
305                 iface.addMetadata( metadata );
306             }
307         }
308     }
309 
310     /**
311      * Validate the entire model.
312      *
313      * @throws ModelValidationException
314      */
315     private void validate( Model model )
316         throws ModelValidationException
317     {
318         model.validate();
319 
320         for ( ModelDefault modelDefault : model.getDefaults() )
321         {
322             modelDefault.validateElement();
323         }
324 
325         for ( ModelClass modelClass : model.getAllClasses() )
326         {
327             modelClass.validate();
328         }
329 
330         for ( ModelClass modelClass : model.getAllClasses() )
331         {
332             for ( ModelField field : modelClass.getAllFields() )
333             {
334                 field.validate();
335             }
336 
337             for ( CodeSegment codeSegment : modelClass.getAllCodeSegments() )
338             {
339                 codeSegment.validate();
340             }
341         }
342     }
343 
344     public void saveModel( Model model, Writer writer )
345         throws ModelloException
346     {
347         throw new ModelloRuntimeException( "Not implemented." );
348     }
349 
350     public Model translate( Reader reader, String inputType, Properties parameters )
351         throws ModelloException
352     {
353         throw new ModelloRuntimeException( "Not implemented." );
354     }
355 
356     public void generate( Model model, String outputType, Properties parameters )
357         throws ModelloException
358     {
359         if ( model == null )
360         {
361             throw new ModelloRuntimeException( "Illegal argument: model == null." );
362         }
363 
364         if ( outputType == null )
365         {
366             throw new ModelloRuntimeException( "Illegal argument: outputType == null." );
367         }
368 
369         if ( parameters == null )
370         {
371             parameters = new Properties();
372         }
373 
374         ModelloGenerator generator = generatorPluginManager.getGeneratorPlugin( outputType );
375 
376         generator.generate( model, parameters );
377     }
378 }