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