package org.exolab.castor.builder.factory;

import org.castor.xml.JavaNaming;
import org.exolab.castor.builder.SGTypes;
import org.exolab.castor.builder.info.CollectionInfo;
import org.exolab.javasource.JClass;
import org.exolab.javasource.JMethod;
import org.exolab.javasource.JParameter;
import org.exolab.javasource.JSourceCode;

/**
 * The Factory for Java2 Collections.
 */
public class CollectionJ2MemberAndAccessorFactory extends CollectionMemberAndAccessorFactory {

  /**
   * Creates a new CollectionJ2MemberAndAccessorFactory.
   * 
   * @param naming the javaNaming to use
   */
  public CollectionJ2MemberAndAccessorFactory(final JavaNaming naming) {
    super(naming);
  }

  /**
   * To the Java-1 collection iterators, we add the Java-2 Iterator.
   */
  @Override
  protected final void createCollectionIterationMethods(final CollectionInfo fieldInfo,
      final JClass jClass, final boolean useJava50) {
    super.createCollectionIterationMethods(fieldInfo, jClass, useJava50);
    this.createIteratorMethod(fieldInfo, jClass, useJava50);
  }

  @Override
  protected final void createEnumerateMethod(final CollectionInfo fieldInfo, final JClass jClass,
      final boolean useJava50) {
    JMethod method = new JMethod("enumerate" + fieldInfo.getMethodSuffix(),
        SGTypes.createEnumeration(fieldInfo.getContentType().getJType(), useJava50, true),
        "an Enumeration over all possible elements of this collection");

    JSourceCode sourceCode = method.getSourceCode();
    sourceCode.add("return java.util.Collections.enumeration(this.");
    sourceCode.append(fieldInfo.getName());
    sourceCode.append(");");

    jClass.addMethod(method);
  }

  @Override
  protected final void createAddMethod(final CollectionInfo fieldInfo, final JClass jClass) {
    JMethod method = new JMethod(fieldInfo.getWriteMethodName());
    method.addException(SGTypes.INDEX_OUT_OF_BOUNDS_EXCEPTION,
        "if the index given is outside the bounds of the collection");
    final JParameter parameter =
        new JParameter(fieldInfo.getContentType().getJType(), fieldInfo.getContentName());
    method.addParameter(parameter);

    JSourceCode sourceCode = method.getSourceCode();
    this.addMaxSizeCheck(fieldInfo, method.getName(), sourceCode);

    sourceCode.add("this.");
    sourceCode.append(fieldInfo.getName());
    sourceCode.append(".add(");
    sourceCode.append(fieldInfo.getContentType().createToJavaObjectCode(parameter.getName()));
    sourceCode.append(");");

    if (fieldInfo.isBound()) {
      this.createBoundPropertyCode(fieldInfo, sourceCode);
    }

    jClass.addMethod(method);
  }

}
