View Javadoc
1   package org.codehaus.modello.core.io;
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 java.io.IOException;
26  import java.io.Reader;
27  import java.util.ArrayList;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  
32  import org.codehaus.modello.ModelloException;
33  import org.codehaus.modello.model.BaseElement;
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.VersionDefinition;
42  import org.codehaus.modello.model.VersionRange;
43  import org.codehaus.plexus.util.xml.pull.MXParser;
44  import org.codehaus.plexus.util.xml.pull.XmlPullParser;
45  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
46  
47  /**
48   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
49   * @author <a href="mailto:evenisse@codehaus.org">Emmanuel Venisse</a>
50   */
51  public class ModelReader {
52      private Map<String, String> modelAttributes = new HashMap<String, String>();
53  
54      private Map<String, Map<String, String>> classAttributes = new HashMap<String, Map<String, String>>();
55  
56      private Map<String, Map<String, String>> interfaceAttributes = new HashMap<String, Map<String, String>>();
57  
58      private Map<String, Map<String, String>> fieldAttributes = new HashMap<String, Map<String, String>>();
59  
60      private Map<String, Map<String, String>> associationAttributes = new HashMap<String, Map<String, String>>();
61  
62      public Map<String, String> getAttributesForModel() {
63          return modelAttributes;
64      }
65  
66      public Map<String, String> getAttributesForClass(ModelClass modelClass) {
67          return classAttributes.get(modelClass.getName());
68      }
69  
70      public Map<String, String> getAttributesForInterface(ModelInterface modelInterface) {
71          return interfaceAttributes.get(modelInterface.getName());
72      }
73  
74      public Map<String, String> getAttributesForField(ModelField modelField) {
75          return fieldAttributes.get(
76                  modelField.getModelClass().getName() + ':' + modelField.getName() + ':' + modelField.getVersionRange());
77      }
78  
79      public Map<String, String> getAttributesForAssociation(ModelAssociation modelAssociation) {
80          return associationAttributes.get(modelAssociation.getModelClass().getName()
81                  + ':'
82                  + modelAssociation.getName()
83                  + ':'
84                  + modelAssociation.getVersionRange());
85      }
86  
87      public Model loadModel(Reader reader) throws ModelloException {
88          try {
89              Model model = new Model();
90  
91              XmlPullParser parser = new MXParser();
92  
93              parser.setInput(reader);
94  
95              parseModel(model, parser);
96  
97              return model;
98          } catch (IOException ex) {
99              throw new ModelloException("Error parsing the model.", ex);
100         } catch (XmlPullParserException ex) {
101             throw new ModelloException("Error parsing the model.", ex);
102         }
103     }
104 
105     public void parseModel(Model model, XmlPullParser parser) throws XmlPullParserException, IOException {
106         int eventType = parser.getEventType();
107 
108         while (eventType != XmlPullParser.END_DOCUMENT) {
109             if (eventType == XmlPullParser.START_TAG) {
110                 if (parseBaseElement(model, parser)) {
111                 } else if ("id".equals(parser.getName())) {
112                     model.setId(parser.nextText());
113                 } else if ("defaults".equals(parser.getName())) {
114                     parseDefaults(model, parser);
115                 } else if ("versionDefinition".equals(parser.getName())) {
116                     parseVersionDefinition(model, parser);
117                 } else if ("interfaces".equals(parser.getName())) {
118                     parseInterfaces(model, parser);
119                 } else if ("classes".equals(parser.getName())) {
120                     parseClasses(model, parser);
121                 } else if ("model".equals(parser.getName())) {
122                     modelAttributes = getAttributes(parser);
123                 } else {
124                     //                    parser.nextText();
125                 }
126             }
127             eventType = parser.next();
128         }
129     }
130 
131     private void parseDefaults(Model model, XmlPullParser parser) throws XmlPullParserException, IOException {
132         while (parser.nextTag() == XmlPullParser.START_TAG) {
133             if ("default".equals(parser.getName())) {
134                 ModelDefault modelDefault = new ModelDefault();
135 
136                 while (parser.nextTag() == XmlPullParser.START_TAG) {
137                     if ("key".equals(parser.getName())) {
138                         modelDefault.setKey(parser.nextText());
139                     } else if ("value".equals(parser.getName())) {
140                         modelDefault.setValue(parser.nextText());
141                     } else {
142                         parser.nextText();
143                     }
144                 }
145 
146                 model.addDefault(modelDefault);
147             } else {
148                 parser.next();
149             }
150         }
151     }
152 
153     private void parseVersionDefinition(Model model, XmlPullParser parser) throws XmlPullParserException, IOException {
154         if ("versionDefinition".equals(parser.getName())) {
155             VersionDefinition versionDefinition = new VersionDefinition();
156 
157             while (parser.nextTag() == XmlPullParser.START_TAG) {
158                 if ("type".equals(parser.getName())) {
159                     versionDefinition.setType(parser.nextText());
160                 } else if ("value".equals(parser.getName())) {
161                     versionDefinition.setValue(parser.nextText());
162                 } else {
163                     parser.nextText();
164                 }
165             }
166 
167             model.setVersionDefinition(versionDefinition);
168         }
169     }
170 
171     private void parseInterfaces(Model model, XmlPullParser parser) throws XmlPullParserException, IOException {
172         while (parser.nextTag() == XmlPullParser.START_TAG) {
173             if ("interface".equals(parser.getName())) {
174                 ModelInterface modelInterface = new ModelInterface();
175 
176                 Map<String, String> attributes = getAttributes(parser);
177 
178                 while (parser.nextTag() == XmlPullParser.START_TAG) {
179                     if (parseBaseElement(modelInterface, parser)) {
180                     } else if ("superInterface".equals(parser.getName())) {
181                         modelInterface.setSuperInterface(parser.nextText());
182                     } else if ("packageName".equals(parser.getName())) {
183                         modelInterface.setPackageName(parser.nextText());
184                     } else if ("codeSegments".equals(parser.getName())) {
185                         parseCodeSegment(modelInterface, parser);
186                     } else {
187                         parser.nextText();
188                     }
189                 }
190 
191                 model.addInterface(modelInterface);
192                 interfaceAttributes.put(modelInterface.getName(), attributes);
193             } else {
194                 parser.next();
195             }
196         }
197     }
198 
199     private void parseClasses(Model model, XmlPullParser parser) throws XmlPullParserException, IOException {
200         while (parser.nextTag() == XmlPullParser.START_TAG) {
201             if ("class".equals(parser.getName())) {
202                 ModelClass modelClass = new ModelClass();
203 
204                 Map<String, String> attributes = getAttributes(parser);
205 
206                 while (parser.nextTag() == XmlPullParser.START_TAG) {
207                     if (parseBaseElement(modelClass, parser)) {
208                     } else if ("interfaces".equals(parser.getName())) {
209                         parseClassInterfaces(modelClass, parser);
210                     } else if ("superClass".equals(parser.getName())) {
211                         modelClass.setSuperClass(parser.nextText());
212                     } else if ("packageName".equals(parser.getName())) {
213                         modelClass.setPackageName(parser.nextText());
214                     } else if ("fields".equals(parser.getName())) {
215                         parseFields(modelClass, parser);
216                     } else if ("codeSegments".equals(parser.getName())) {
217                         parseCodeSegment(modelClass, parser);
218                     } else {
219                         parser.nextText();
220                     }
221                 }
222 
223                 model.addClass(modelClass);
224                 classAttributes.put(modelClass.getName(), attributes);
225             } else {
226                 parser.next();
227             }
228         }
229     }
230 
231     private void parseClassInterfaces(ModelClass modelClass, XmlPullParser parser)
232             throws IOException, XmlPullParserException {
233         while (parser.nextTag() == XmlPullParser.START_TAG) {
234             if ("interface".equals(parser.getName())) {
235                 modelClass.addInterface(parser.nextText());
236             } else {
237                 parser.nextText();
238             }
239         }
240     }
241 
242     private void parseFields(ModelClass modelClass, XmlPullParser parser) throws XmlPullParserException, IOException {
243         while (parser.nextTag() == XmlPullParser.START_TAG) {
244             if ("field".equals(parser.getName())) {
245                 ModelField modelField = new ModelField();
246 
247                 ModelAssociation modelAssociation = null;
248 
249                 Map<String, String> fAttributes = getAttributes(parser);
250 
251                 Map<String, String> aAttributes = new HashMap<String, String>();
252 
253                 while (parser.nextTag() == XmlPullParser.START_TAG) {
254                     if (parseBaseElement(modelField, parser)) {
255                     } else if ("association".equals(parser.getName())) {
256                         aAttributes = getAttributes(parser);
257 
258                         modelAssociation = parseAssociation(parser);
259                     } else if ("alias".equals(parser.getName())) {
260                         modelField.setAlias(parser.nextText());
261                     } else if ("type".equals(parser.getName())) {
262                         modelField.setType(parser.nextText());
263                     } else if ("defaultValue".equals(parser.getName())) {
264                         modelField.setDefaultValue(parser.nextText());
265                     } else if ("typeValidator".equals(parser.getName())) {
266                         modelField.setTypeValidator(parser.nextText());
267                     } else if ("required".equals(parser.getName())) {
268                         modelField.setRequired(Boolean.valueOf(parser.nextText()));
269                     } else if ("identifier".equals(parser.getName())) {
270                         modelField.setIdentifier(
271                                 Boolean.valueOf(parser.nextText()).booleanValue());
272                     } else {
273                         parser.nextText();
274                     }
275                 }
276 
277                 if (modelField.getName() != null) {
278                     fieldAttributes.put(
279                             modelClass.getName() + ":" + modelField.getName() + ":" + modelField.getVersionRange(),
280                             fAttributes);
281                 }
282 
283                 if (modelAssociation != null) {
284                     // Base element
285                     modelAssociation.setName(modelField.getName());
286 
287                     modelAssociation.setDescription(modelField.getDescription());
288 
289                     modelAssociation.setVersionRange(modelField.getVersionRange());
290 
291                     modelAssociation.setComment(modelField.getComment());
292 
293                     modelAssociation.setAnnotations(modelField.getAnnotations());
294 
295                     // model field fields
296                     modelAssociation.setType(modelField.getType());
297 
298                     modelAssociation.setAlias(modelField.getAlias());
299 
300                     modelAssociation.setDefaultValue(modelField.getDefaultValue());
301 
302                     modelAssociation.setTypeValidator(modelField.getTypeValidator());
303 
304                     modelAssociation.setRequired(modelField.isRequired());
305 
306                     modelAssociation.setIdentifier(modelField.isIdentifier());
307 
308                     if (modelAssociation.getName() != null) {
309                         associationAttributes.put(
310                                 modelClass.getName() + ":" + modelAssociation.getName() + ":"
311                                         + modelAssociation.getVersionRange(),
312                                 aAttributes);
313                     }
314 
315                     modelClass.addField(modelAssociation);
316                 } else {
317                     modelClass.addField(modelField);
318                 }
319             } else {
320                 parser.next();
321             }
322         }
323     }
324 
325     private ModelAssociation parseAssociation(XmlPullParser parser) throws XmlPullParserException, IOException {
326         ModelAssociation modelAssociation = new ModelAssociation();
327 
328         while (parser.nextTag() == XmlPullParser.START_TAG) {
329             if (parseBaseElement(modelAssociation, parser)) {
330             } else if ("type".equals(parser.getName())) {
331                 modelAssociation.setTo(parser.nextText());
332             } else if ("multiplicity".equals(parser.getName())) {
333                 modelAssociation.setMultiplicity(parser.nextText());
334             } else {
335                 parser.nextText();
336             }
337         }
338 
339         return modelAssociation;
340     }
341 
342     private void parseCodeSegment(ModelClass modelClass, XmlPullParser parser)
343             throws XmlPullParserException, IOException {
344         while (parser.nextTag() == XmlPullParser.START_TAG) {
345             if ("codeSegment".equals(parser.getName())) {
346                 CodeSegment codeSegment = new CodeSegment();
347 
348                 while (parser.nextTag() == XmlPullParser.START_TAG) {
349                     if (parseBaseElement(codeSegment, parser)) {
350                     } else if ("code".equals(parser.getName())) {
351                         codeSegment.setCode(parser.nextText());
352                     } else {
353                         parser.nextText();
354                     }
355                 }
356 
357                 modelClass.addCodeSegment(codeSegment);
358             } else {
359                 parser.next();
360             }
361         }
362     }
363 
364     private void parseCodeSegment(ModelInterface modelInterface, XmlPullParser parser)
365             throws XmlPullParserException, IOException {
366         while (parser.nextTag() == XmlPullParser.START_TAG) {
367             if ("codeSegment".equals(parser.getName())) {
368                 CodeSegment codeSegment = new CodeSegment();
369 
370                 while (parser.nextTag() == XmlPullParser.START_TAG) {
371                     if (parseBaseElement(codeSegment, parser)) {
372                     } else if ("code".equals(parser.getName())) {
373                         codeSegment.setCode(parser.nextText());
374                     } else {
375                         parser.nextText();
376                     }
377                 }
378 
379                 modelInterface.addCodeSegment(codeSegment);
380             } else {
381                 parser.next();
382             }
383         }
384     }
385 
386     private boolean parseBaseElement(BaseElement element, XmlPullParser parser)
387             throws XmlPullParserException, IOException {
388         if ("name".equals(parser.getName())) {
389             element.setName(parser.nextText());
390         } else if ("description".equals(parser.getName())) {
391             element.setDescription(parser.nextText());
392         } else if ("version".equals(parser.getName())) {
393             element.setVersionRange(new VersionRange(parser.nextText()));
394         } else if ("comment".equals(parser.getName())) {
395             element.setComment(parser.nextText());
396         } else if ("annotations".equals(parser.getName())) {
397             List<String> annotationsList = new ArrayList<String>();
398             while (parser.nextTag() == XmlPullParser.START_TAG) {
399                 if ("annotation".equals(parser.getName())) {
400                     annotationsList.add(parser.nextText());
401                 }
402             }
403             element.setAnnotations(annotationsList);
404         } else {
405             return false;
406         }
407 
408         return true;
409     }
410 
411     private Map<String, String> getAttributes(XmlPullParser parser) {
412         Map<String, String> attributes = new HashMap<String, String>();
413 
414         for (int i = 0; i < parser.getAttributeCount(); i++) {
415             String name = parser.getAttributeName(i);
416 
417             String value = parser.getAttributeValue(i);
418 
419             attributes.put(name, value);
420         }
421 
422         return attributes;
423     }
424 }