View Javadoc
1   package org.exolab.castor.builder.factory;
2   
3   import org.apache.commons.lang.StringUtils;
4   import org.castor.xml.JavaNaming;
5   import org.exolab.castor.builder.AnnotationBuilder;
6   import org.exolab.castor.builder.SGTypes;
7   import org.exolab.castor.builder.info.CollectionInfo;
8   import org.exolab.castor.builder.info.FieldInfo;
9   import org.exolab.castor.builder.info.nature.XMLInfoNature;
10  import org.exolab.castor.builder.types.XSType;
11  import org.exolab.javasource.JArrayType;
12  import org.exolab.javasource.JClass;
13  import org.exolab.javasource.JCollectionType;
14  import org.exolab.javasource.JDocComment;
15  import org.exolab.javasource.JDocDescriptor;
16  import org.exolab.javasource.JMethod;
17  import org.exolab.javasource.JParameter;
18  import org.exolab.javasource.JSourceCode;
19  import org.exolab.javasource.JType;
20  
21  /**
22   * This factory takes a CollectionInfo and generates the suitable JFields
23   * and the accessor methods into the JClass.
24   */
25  public class CollectionMemberAndAccessorFactory extends FieldMemberAndAccessorFactory {
26  
27      /**
28       * Creates a factory that offers public methods to create the 
29       * field initialization code as well as the accessor methods.
30       * 
31       * @param naming JavaNaming to use
32       */
33      public CollectionMemberAndAccessorFactory(final JavaNaming naming) {
34          super(naming);
35      }
36  
37      /**
38       * {@inheritDoc}
39       */
40      public void generateInitializerCode(final FieldInfo fieldInfo, 
41              final JSourceCode sourceCode) {
42          CollectionInfo collectionInfo = (CollectionInfo) fieldInfo;
43          sourceCode.add("this.");
44          sourceCode.append(fieldInfo.getName());
45          sourceCode.append(" = new ");
46          JType jType = collectionInfo.getXSList().getJType();
47          sourceCode.append(((JCollectionType) jType).getInstanceName());
48          sourceCode.append("();");
49          
50          if (!StringUtils.isEmpty(fieldInfo.getDefaultValue())) {
51            StringBuffer buffer = new StringBuffer();
52            buffer.append(fieldInfo.getName());
53            buffer.append(".add(");
54            buffer.append(fieldInfo.getDefaultValue());
55            buffer.append(");");
56            sourceCode.add(buffer.toString());
57          }
58      } // -- generateConstructorCode
59  
60      /**
61       * {@inheritDoc}
62       */
63      public final void createAccessMethods(final FieldInfo fieldInfo, 
64              final JClass jClass, final boolean useJava50, 
65              final AnnotationBuilder[] annotationBuilders) {
66          CollectionInfo collectionInfo = (CollectionInfo) fieldInfo;
67          this.createAddAndRemoveMethods(collectionInfo, jClass);
68          this.createGetAndSetMethods(collectionInfo, jClass, useJava50, annotationBuilders);
69          this.createGetCountMethod(collectionInfo, jClass);
70          this.createCollectionIterationMethods(collectionInfo, jClass, useJava50);
71      } // -- createAccessMethods
72      
73      /**
74       * Creates the add method for this collection.
75       * 
76       * @param fieldInfo the collectionInfo to translate
77       * @param jClass the jClass to add the method to.
78       */
79      protected void createAddMethod(final CollectionInfo fieldInfo, 
80              final JClass jClass) {
81          JMethod method = new JMethod(fieldInfo.getWriteMethodName());
82          method.addException(SGTypes.INDEX_OUT_OF_BOUNDS_EXCEPTION,
83                  "if the index given is outside the bounds of the collection");
84          final JParameter parameter = new JParameter(
85                  fieldInfo.getContentType().getJType(), fieldInfo.getContentName());
86          method.addParameter(parameter);
87  
88          JSourceCode sourceCode = method.getSourceCode();
89          this.addMaxSizeCheck(fieldInfo, method.getName(), sourceCode);
90  
91          sourceCode.add("this.");
92          sourceCode.append(fieldInfo.getName());
93          sourceCode.append(".addElement(");
94          sourceCode.append(fieldInfo.getContentType().createToJavaObjectCode(parameter.getName()));
95          sourceCode.append(");");
96  
97          if (fieldInfo.isBound()) {
98              this.createBoundPropertyCode(fieldInfo, sourceCode);
99          }
100 
101         jClass.addMethod(method);
102     }
103 
104     /**
105      * Creates bound property code..
106      * 
107      * @param fieldInfo the collectionInfo to translate
108      * @param sourceCode the sourceCode to attach to
109      */
110     protected void createBoundPropertyCode(final CollectionInfo fieldInfo, 
111             final JSourceCode sourceCode) {
112         sourceCode.add("notifyPropertyChangeListeners(\"");
113         String fieldName = fieldInfo.getName();
114         if (fieldName.startsWith("_")) {
115             sourceCode.append(fieldName.substring(1));
116         } else {
117             sourceCode.append(fieldName);
118         }
119         sourceCode.append("\", null, ");
120         sourceCode.append(fieldName);
121         sourceCode.append(");");
122     } // -- createBoundPropertyCode
123 
124     /**
125      * Creates the enumerate method.
126      * 
127      * @param fieldInfo the collectionInfo to translate
128      * @param jClass the jClass to add the method to.
129      * @param useJava50 java version flag
130      */
131     protected void createEnumerateMethod(final CollectionInfo fieldInfo, 
132             final JClass jClass, final boolean useJava50) {
133         JMethod method = new JMethod("enumerate" + fieldInfo.getMethodSuffix(),
134                 SGTypes.createEnumeration(fieldInfo.getContentType().getJType(), useJava50, true),
135                 "an Enumeration over all " + fieldInfo.getContentType().getJType() + " elements");
136 
137         JSourceCode sourceCode = method.getSourceCode();
138         sourceCode.add("return this.");
139         sourceCode.append(fieldInfo.getName());
140         sourceCode.append(".elements();");
141 
142         jClass.addMethod(method);
143     }
144 
145     /**
146      * Returns true if extra collection methods should be generated. The extra
147      * collection methods are methods which return an actual reference to the
148      * underlying collection as opposed to an enumeration, iterator, or copy.
149      *
150      * @param fieldInfo the collectionInfo to translate
151      * @return true if extra collection methods should be generated
152      */
153     private boolean createExtraMethods(final CollectionInfo fieldInfo) {
154         return fieldInfo.isExtraMethods();
155     } // -- extraMethods
156 
157     /**
158      * Creates the get as array method.
159      * 
160      * @param fieldInfo the collectionInfo to translate
161      * @param jClass the jClass to add the method to.
162      * @param useJava50 java version flag
163      * @param annotationBuilders the custom builders
164      */
165     private void createGetAsArrayMethod(final CollectionInfo fieldInfo, 
166             final JClass jClass, final boolean useJava50, 
167             AnnotationBuilder[] annotationBuilders) {
168         JType baseType = fieldInfo.getContentType().getJType();
169         JType arrayType = new JArrayType(baseType, useJava50);
170         JMethod method = new JMethod(fieldInfo.getReadMethodName(), arrayType,
171                                      "this collection as an Array");
172 
173         JSourceCode sourceCode = method.getSourceCode();
174 
175         // create Javadoc
176         JDocComment comment = method.getJDocComment();
177         comment.appendComment("Returns the contents of the collection in an Array.  ");
178 
179         if (!(baseType.isPrimitive())) {
180             // For non-primitive types, we use the API method made for this purpose
181             comment.appendComment("<p>");
182             comment.appendComment("Note:  Just in case the collection contents are changing in ");
183             comment.appendComment("another thread, we pass a 0-length Array of the correct type ");
184             comment.appendComment("into the API call.  This way we <i>know</i> that the Array ");
185             comment.appendComment("returned is of exactly the correct length.");
186 
187             String baseTypeName = baseType.toString();
188             if (baseType.isArray()) {
189                 sourceCode.add(arrayType.toString() + " array = new ");
190                 sourceCode.append(baseTypeName.substring(0, baseTypeName.length() - 2) + "[0][];");
191             } else {
192                 sourceCode.add(arrayType.toString() + " array = new ");
193                 sourceCode.append(baseTypeName + "[0];");
194             }
195             
196             sourceCode.add("return ");
197             
198             if (!useJava50) {
199                sourceCode.add("(");
200                sourceCode.add(arrayType.toString());
201                sourceCode.add(") ");
202             }
203             sourceCode.append("this." + fieldInfo.getName() + ".toArray(array);");
204         } else {
205             // For primitive types, we have to do this the hard way
206             sourceCode.add("int size = this.");
207             sourceCode.append(fieldInfo.getName());
208             sourceCode.append(".size();");
209 
210             sourceCode.add(arrayType.toString());
211             sourceCode.append(" array = new ");
212             // the first brackets must contain the size...
213             int brackets = arrayType.toString().indexOf("[]");
214             sourceCode.append(arrayType.toString().substring(0, brackets));
215             sourceCode.append("[size]");
216             sourceCode.append(";");
217             sourceCode.add("java.util.Iterator iter = " + fieldInfo.getName() + ".iterator();");
218 
219             String value = "iter.next()";
220             sourceCode.add("for (int index = 0; index < size; index++) {");
221             sourceCode.indent();
222             sourceCode.add("array[index] = ");
223             if (fieldInfo.getContentType().getType() == XSType.CLASS) {
224                 sourceCode.append("(");
225                 sourceCode.append(arrayType.getName());
226                 sourceCode.append(") ");
227                 sourceCode.append(value);
228             } else {
229                 sourceCode.append(fieldInfo.getContentType().createFromJavaObjectCode(value));
230             }
231             sourceCode.append(";");
232             sourceCode.unindent();
233             sourceCode.add("}");
234 
235             sourceCode.add("return array;");
236         }
237         
238         // add custom annotations
239         for (int i = 0; i < annotationBuilders.length; i++) {
240             AnnotationBuilder annotationBuilder = annotationBuilders[i];
241             annotationBuilder.addFieldGetterAnnotations(fieldInfo, method);
242         }
243 
244         jClass.addMethod(method);
245     }
246 
247     /**
248      * Creates the get as reference method.
249      * 
250      * @param fieldInfo the collectionInfo to translate
251      * @param jClass the jClass to add the method to.
252      */
253     private void createGetAsReferenceMethod(final CollectionInfo fieldInfo, 
254             final JClass jClass) {
255         JMethod method = new JMethod(fieldInfo.getReadMethodName() 
256                 + fieldInfo.getReferenceMethodSuffix(),
257                 fieldInfo.getXSList().getJType(),
258                 "a reference to the Vector backing this class");
259 
260         // create Javadoc
261         JDocComment comment = method.getJDocComment();
262         comment.appendComment("Returns a reference to '");
263         comment.appendComment(fieldInfo.getName());
264         comment.appendComment("'. No type checking is performed on any ");
265         comment.appendComment("modifications to the Vector.");
266 
267         // create code
268         JSourceCode sourceCode = method.getSourceCode();
269         sourceCode.add("return this.");
270         sourceCode.append(fieldInfo.getName());
271         sourceCode.append(";");
272 
273         jClass.addMethod(method);
274     }
275 
276     /**
277      * Creates the get by index method.
278      * 
279      * @param fieldInfo the collectionInfo to translate
280      * @param jClass the jClass to add the method to.
281     * @param useJava50 
282      */
283     protected void createGetByIndexMethod(final CollectionInfo fieldInfo, 
284             final JClass jClass, boolean useJava50) {
285         XSType contentType = fieldInfo.getContentType();
286         JMethod method = new JMethod(fieldInfo.getReadMethodName(), contentType.getJType(),
287                 "the value of the " + contentType.getJType().toString() + " at the given index");
288 
289         method.addException(SGTypes.INDEX_OUT_OF_BOUNDS_EXCEPTION,
290                 "if the index given is outside the bounds of the collection");
291         method.addParameter(new JParameter(JType.INT, "index"));
292 
293         JSourceCode sourceCode = method.getSourceCode();
294         this.addIndexCheck(fieldInfo, sourceCode, method.getName());
295 
296         String value = fieldInfo.getName() + ".get(index)";
297         sourceCode.add("return ");
298         if (contentType.getType() == XSType.CLASS) {
299            if (!useJava50) {
300               sourceCode.append("(");
301               sourceCode.append(method.getReturnType().toString());
302               sourceCode.append(") ");
303            }
304            sourceCode.append(value);
305         } else {
306             sourceCode.append(contentType.createFromJavaObjectCode(value));
307         }
308         sourceCode.append(";");
309 
310         jClass.addMethod(method);
311     }
312 
313     /**
314      * Creates the add/add by index/remove/remove by index/remove all methods.
315      * 
316      * @param fieldInfo the collectionInfo to translate
317      * @param jClass the jClass to add the method to.
318      */
319     private void createAddAndRemoveMethods(final CollectionInfo fieldInfo, 
320             final JClass jClass) {
321         // create add methods
322         this.createAddMethod(fieldInfo, jClass);
323         this.createAddByIndexMethod(fieldInfo, jClass);
324 
325         // create remove methods
326         this.createRemoveObjectMethod(fieldInfo, jClass);
327         this.createRemoveByIndexMethod(fieldInfo, jClass);
328         this.createRemoveAllMethod(fieldInfo,jClass);
329     }
330 
331     /**
332      * Creates the getter and setter methods.
333      * 
334      * @param fieldInfo the collectionInfo to translate
335      * @param jClass the jClass to add the method to.
336      * @param useJava50 java version flag
337      * @param annotationBuilders the custom annotationBuilders
338      */
339     private void createGetAndSetMethods(final CollectionInfo fieldInfo, 
340             final JClass jClass, final boolean useJava50,
341             final AnnotationBuilder[] annotationBuilders) {
342         // create get methods
343         this.createGetByIndexMethod(fieldInfo, jClass, useJava50);
344         this.createGetAsArrayMethod(fieldInfo, jClass, useJava50, annotationBuilders);
345         if (this.createExtraMethods(fieldInfo)) {
346             this.createGetAsReferenceMethod(fieldInfo, jClass);
347         }
348 
349         // create set methods
350         this.createSetByIndexMethod(fieldInfo, jClass);
351         this.createSetAsArrayMethod(fieldInfo, jClass, useJava50);
352         if (this.createExtraMethods(fieldInfo)) {
353             this.createSetAsCopyMethod(fieldInfo, jClass);
354             this.createSetAsReferenceMethod(fieldInfo, jClass, useJava50);
355         }
356     }
357 
358     /**
359      * Creates the get count method.
360      * 
361      * @param fieldInfo the collectionInfo to translate
362      * @param jClass the jClass to add the method to.
363      */
364     private void createGetCountMethod(final CollectionInfo fieldInfo, 
365             final JClass jClass) {
366         JMethod method = new JMethod(fieldInfo.getReadMethodName() + "Count", JType.INT,
367                                      "the size of this collection");
368 
369         JSourceCode sourceCode = method.getSourceCode();
370         sourceCode.add("return this.");
371         sourceCode.append(fieldInfo.getName());
372         sourceCode.append(".size();");
373 
374         jClass.addMethod(method);
375     }
376 
377     /**
378      * Generate methods for iterating over the objects in the collection. For
379      * Java-1 collections, we only generate an Enumerator. Implementations for
380      * other versions of Java should call this method for backward compatbility
381      * and then add any additional new methods.
382      *
383      * @param fieldInfo the collectionI to translate
384      * @param jClass the JClass to which we add this method
385      * @param useJava50
386      *            true if source code is supposed to be generated for Java 5
387      */
388     protected void createCollectionIterationMethods(final CollectionInfo fieldInfo, 
389             final JClass jClass, final boolean useJava50) {
390         this.createEnumerateMethod(fieldInfo, jClass, useJava50);
391     } // -- createCollectionAccessMethods
392 
393     /**
394      * Creates the add by index method.
395      * 
396      * @param fieldInfo the collectionInfo to translate
397      * @param jClass the jClass to add the method to.
398      * @param useJava50 java version flag
399      */
400     protected void createAddByIndexMethod(final CollectionInfo fieldInfo, 
401             final JClass jClass) {
402         JMethod method = new JMethod(fieldInfo.getWriteMethodName());
403         method.addException(SGTypes.INDEX_OUT_OF_BOUNDS_EXCEPTION,
404                             "if the index given is outside the bounds of the collection");
405         method.addParameter(new JParameter(JType.INT, "index"));
406         final JParameter parameter = new JParameter(
407         		fieldInfo.getContentType().getJType(), fieldInfo.getContentName());
408         method.addParameter(parameter);
409 
410         JSourceCode sourceCode = method.getSourceCode();
411         this.addMaxSizeCheck(fieldInfo, method.getName(), sourceCode);
412 
413         sourceCode.add("this.");
414         sourceCode.append(fieldInfo.getName());
415         sourceCode.append(".add(index, ");
416         sourceCode.append(fieldInfo.getContentType().createToJavaObjectCode(parameter.getName()));
417         sourceCode.append(");");
418 
419         if (fieldInfo.isBound()) {
420             this.createBoundPropertyCode(fieldInfo, sourceCode);
421         }
422 
423         jClass.addMethod(method);
424     }
425 
426     /**
427      * Creates the iterate method.
428      * 
429      * @param fieldInfo the collectionInfo to translate
430      * @param jClass the jClass to add the method to.
431      * @param useJava50 java version flag
432      */
433     protected void createIteratorMethod(final CollectionInfo fieldInfo, 
434             final JClass jClass, final boolean useJava50) {
435         JMethod method = new JMethod("iterate" + fieldInfo.getMethodSuffix(),
436                 SGTypes.createIterator(fieldInfo.getContentType().getJType(), useJava50, true),
437                 "an Iterator over all possible elements in this collection");
438 
439         JSourceCode sourceCode = method.getSourceCode();
440         sourceCode.add("return this.");
441         sourceCode.append(fieldInfo.getName());
442         sourceCode.append(".iterator();");
443 
444         jClass.addMethod(method);
445     }
446 
447     /**
448      * Creates the remove all method.
449      * 
450      * @param fieldInfo the collectionInfo to translate
451      * @param jClass the jClass to add the method to.
452      */
453     private void createRemoveAllMethod(final CollectionInfo fieldInfo, 
454             final JClass jClass) {
455         JMethod method = new JMethod("removeAll" + fieldInfo.getMethodSuffix());
456 
457         JSourceCode sourceCode = method.getSourceCode();
458         sourceCode.add("this.");
459         sourceCode.append(fieldInfo.getName());
460         sourceCode.append(".clear();");
461 
462         if (fieldInfo.isBound()) {
463             this.createBoundPropertyCode(fieldInfo, sourceCode);
464         }
465 
466         jClass.addMethod(method);
467     }
468 
469     /**
470      * Creates the remove by index method.
471      * 
472      * @param fieldInfo the collectionInfo to translate
473      * @param jClass the jClass to add the method to.
474      */
475     protected void createRemoveByIndexMethod(final CollectionInfo fieldInfo, 
476             final JClass jClass) {
477         JMethod method = new JMethod("remove" + fieldInfo.getMethodSuffix() + "At",
478                 fieldInfo.getContentType().getJType(),
479                 "the element removed from the collection");
480 
481         method.addParameter(new JParameter(JType.INT, "index"));
482 
483         JSourceCode sourceCode = method.getSourceCode();
484         sourceCode.add("java.lang.Object obj = this.");
485         sourceCode.append(fieldInfo.getName());
486         sourceCode.append(".remove(index);");
487 
488         if (fieldInfo.isBound()) {
489             this.createBoundPropertyCode(fieldInfo, sourceCode);
490         }
491 
492         sourceCode.add("return ");
493         if (fieldInfo.getContentType().getType() == XSType.CLASS) {
494             sourceCode.append("(");
495             sourceCode.append(method.getReturnType().getName());
496             sourceCode.append(") obj;");
497         } else {
498             sourceCode.append(fieldInfo.getContentType().createFromJavaObjectCode("obj"));
499             sourceCode.append(";");
500         }
501 
502         jClass.addMethod(method);
503     }
504 
505     /**
506      * Creates the remove by object method.
507      * 
508      * @param fieldInfo the collectionInfo to translate
509      * @param jClass the jClass to add the method to.
510      */
511     private void createRemoveObjectMethod(final CollectionInfo fieldInfo, 
512             final JClass jClass) {
513         JMethod method = new JMethod("remove" + fieldInfo.getMethodSuffix(), JType.BOOLEAN,
514                                      "true if the object was removed from the collection.");
515 
516         final JParameter parameter = new JParameter(fieldInfo.getContentType().getJType(),
517                 fieldInfo.getContentName());
518         method.addParameter(parameter);
519 
520         JSourceCode sourceCode = method.getSourceCode();
521         sourceCode.add("boolean removed = ");
522         sourceCode.append(fieldInfo.getName());
523         sourceCode.append(".remove(");
524         sourceCode.append(fieldInfo.getContentType().createToJavaObjectCode(parameter.getName()));
525         sourceCode.append(");");
526 
527         if (fieldInfo.isBound()) {
528             this.createBoundPropertyCode(fieldInfo, sourceCode);
529         }
530 
531         sourceCode.add("return removed;");
532 
533         jClass.addMethod(method);
534     }
535 
536     /**
537      * Creates the set as array method.
538      * 
539      * @param fieldInfo the collectionInfo to translate
540      * @param jClass the jClass to add the method to.
541      * @param useJava50 java version flag
542      */
543     private void createSetAsArrayMethod(final CollectionInfo fieldInfo, 
544             final JClass jClass, final boolean useJava50) {
545         JMethod method = new JMethod("set" + fieldInfo.getMethodSuffix());
546         final JParameter parameter = new JParameter(new JArrayType(
547                 fieldInfo.getContentType().getJType(), useJava50), 
548                 fieldInfo.getContentName() + "Array");
549         method.addParameter(parameter);
550 
551         JSourceCode sourceCode = method.getSourceCode();
552         String index = "i";
553         if (parameter.getName().equals(index)) {
554             index = "j";
555         }
556 
557         sourceCode.add("//-- copy array");
558         sourceCode.add(fieldInfo.getName());
559         sourceCode.append(".clear();");
560         sourceCode.add("");
561         sourceCode.add("for (int ");
562         sourceCode.append(index);
563         sourceCode.append(" = 0; ");
564         sourceCode.append(index);
565         sourceCode.append(" < ");
566         sourceCode.append(parameter.getName());
567         sourceCode.append(".length; ");
568         sourceCode.append(index);
569         sourceCode.append("++) {");
570         sourceCode.indent();
571         sourceCode.addIndented("this.");
572         sourceCode.append(fieldInfo.getName());
573         sourceCode.append(".add(");
574         sourceCode.append(fieldInfo.getContentType().createToJavaObjectCode(
575                 parameter.getName() + "[" + index + "]"));
576         sourceCode.append(");");
577         sourceCode.unindent();
578         sourceCode.add("}");
579 
580         if (fieldInfo.isBound()) {
581             this.createBoundPropertyCode(fieldInfo, sourceCode);
582         }
583 
584         jClass.addMethod(method);
585     }
586 
587     /**
588      * Creates the set as copy method.
589      * 
590      * @param fieldInfo the collectionInfo to translate
591      * @param jClass the jClass to add the method to.
592      */
593     private void createSetAsCopyMethod(final CollectionInfo fieldInfo, 
594             final JClass jClass) {
595         JMethod method = new JMethod("set" + fieldInfo.getMethodSuffix());
596         JParameter parameter = new JParameter(fieldInfo.getXSList().getJType(),
597                 fieldInfo.getContentName() + "List");
598         method.addParameter(parameter);
599 
600         // create Javadoc
601         JDocComment comment = method.getJDocComment();
602         comment.appendComment("Sets the value of '");
603         comment.appendComment(fieldInfo.getName());
604         comment.appendComment(
605                 "' by copying the given Vector. All elements will be checked for type safety.");
606         JDocDescriptor jDesc = comment.getParamDescriptor(parameter.getName());
607         jDesc.setDescription("the Vector to copy.");
608 
609         // create code
610         JSourceCode sourceCode = method.getSourceCode();
611 
612         sourceCode.add("// copy vector");
613         sourceCode.add("this.");
614         sourceCode.append(fieldInfo.getName());
615         sourceCode.append(".clear();");
616         sourceCode.add("");
617 
618         sourceCode.add("this.");
619         sourceCode.append(fieldInfo.getName());
620         sourceCode.append(".addAll(");
621         sourceCode.append(parameter.getName());
622         sourceCode.append(");");
623 
624         if (fieldInfo.isBound()) {
625             this.createBoundPropertyCode(fieldInfo, sourceCode);
626         }
627 
628         jClass.addMethod(method);
629     }
630 
631     /**
632      * Creates the set as reference method.
633      * 
634      * @param fieldInfo the collectionInfo to translate
635      * @param jClass the jClass to add the method to.
636      * @param useJava50 java version flag
637      */
638     private void createSetAsReferenceMethod(final CollectionInfo fieldInfo, 
639             final JClass jClass, final boolean useJava50) {
640         JMethod method = new JMethod("set" + fieldInfo.getMethodSuffix() 
641                 + fieldInfo.getReferenceSuffix());
642         final JType collectionJType = new XMLInfoNature(fieldInfo).getSchemaType().getJType();
643         JParameter parameter = new JParameter(
644                 collectionJType, fieldInfo.getParameterPrefix() + collectionJType.getLocalName());
645         method.addParameter(parameter);
646 
647         // create Javadoc
648         JDocComment comment = method.getJDocComment();
649         comment.appendComment("Sets the value of '");
650         comment.appendComment(fieldInfo.getName());
651         comment.appendComment("' by setting it to the given Vector.");
652         comment.appendComment(" No type checking is performed.");
653         comment.appendComment("\n@deprecated");
654         JDocDescriptor jDesc = comment.getParamDescriptor(parameter.getName());
655         jDesc.setDescription("the Vector to set.");
656 
657         // create code
658         JSourceCode sourceCode = method.getSourceCode();
659         sourceCode.add("this.");
660         sourceCode.append(fieldInfo.getName());
661         sourceCode.append(" = ");
662         sourceCode.append(parameter.getName());
663         sourceCode.append(";");
664 
665         if (fieldInfo.isBound()) {
666             this.createBoundPropertyCode(fieldInfo, sourceCode);
667         }
668 
669         jClass.addMethod(method);
670     }
671 
672     /**
673      * Creates the set by index method.
674      * 
675      * @param fieldInfo the collectionInfo to translate
676      * @param jClass the jClass to add the method to.
677      */
678     protected void createSetByIndexMethod(final CollectionInfo fieldInfo, 
679             final JClass jClass) {
680         JMethod method = new JMethod("set" + fieldInfo.getMethodSuffix());
681 
682         method.addException(SGTypes.INDEX_OUT_OF_BOUNDS_EXCEPTION,
683                             "if the index given is outside the bounds of the collection");
684         method.addParameter(new JParameter(JType.INT, "index"));
685         method.addParameter(new JParameter(fieldInfo.getContentType().getJType(),
686                 fieldInfo.getContentName()));
687 
688         JSourceCode sourceCode = method.getSourceCode();
689         this.addIndexCheck(fieldInfo, sourceCode, method.getName());
690 
691         sourceCode.add("this.");
692         sourceCode.append(fieldInfo.getName());
693         sourceCode.append(".set(index, ");
694         sourceCode.append(fieldInfo.getContentType().createToJavaObjectCode(
695                 fieldInfo.getContentName()));
696         sourceCode.append(");");
697 
698         if (fieldInfo.isBound()) {
699             this.createBoundPropertyCode(fieldInfo, sourceCode);
700         }
701 
702         jClass.addMethod(method);
703     }
704     
705     /**
706      * Creates the add max size check.
707      * 
708      * @param fieldInfo the collectionInfo to translate
709      * @param methodName the method name
710      * @param sourceCode the sourceCode to attach to
711      */
712     protected void addMaxSizeCheck(final CollectionInfo fieldInfo, 
713             final String methodName, final JSourceCode sourceCode) {
714         if (fieldInfo.getXSList().getMaximumSize() > 0) {
715             final String size = Integer.toString(fieldInfo.getXSList().getMaximumSize());
716 
717             sourceCode.add("// check for the maximum size");
718             sourceCode.add("if (this.");
719             sourceCode.append(fieldInfo.getName());
720             sourceCode.append(".size() >= ");
721             sourceCode.append(size);
722             sourceCode.append(") {");
723             sourceCode.indent();
724             sourceCode.add("throw new IndexOutOfBoundsException(\"");
725             sourceCode.append(methodName);
726             sourceCode.append(" has a maximum of ");
727             sourceCode.append(size);
728             sourceCode.append("\");");
729             sourceCode.unindent();
730             sourceCode.add("}");
731             sourceCode.add("");
732         }
733     }
734     
735     /**
736      * Creates the index check.
737      * 
738      * @param fieldInfo the collectionInfo to translate
739      * @param methodName the method name
740      * @param sourceCode the sourceCode to attach to
741      */
742     private void addIndexCheck(final CollectionInfo fieldInfo, 
743             final JSourceCode sourceCode, final String methodName) {
744         sourceCode.add("// check bounds for index");
745         sourceCode.add("if (index < 0 || index >= this.");
746         sourceCode.append(fieldInfo.getName());
747         sourceCode.append(".size()) {");
748 
749         sourceCode.indent();
750         sourceCode.add("throw new IndexOutOfBoundsException(\"");
751         sourceCode.append(methodName);
752         sourceCode.append(": Index value '\" + index + \"' not in range [0..\" + (this.");
753         sourceCode.append(fieldInfo.getName());
754         sourceCode.append(".size() - 1) + \"]\");");
755         sourceCode.unindent();
756         sourceCode.add("}");
757         sourceCode.add("");
758     }
759 
760 
761 }