package org.exolab.castor.builder.factory;

import org.castor.xml.JavaNaming;
import org.exolab.castor.builder.SGTypes;
import org.exolab.castor.builder.info.FieldInfo;
import org.exolab.castor.builder.info.nature.XMLInfoNature;
import org.exolab.javasource.JMethod;
import org.exolab.javasource.JParameter;
import org.exolab.javasource.JSourceCode;
import org.exolab.javasource.JType;

/**
 * This class translates a fieldInfo describing an identity into the suitable getter<7setter
 * methods.
 */
public class IdentityMemberAndAccessorFactory extends FieldMemberAndAccessorFactory {

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

  /**
   * Creats the getter/setter and getReferenceId methods.
   * 
   * @param fieldInfo the fieldInfo to translate
   * @return the created methods
   */
  public JMethod[] createAccessMethods(final FieldInfo fieldInfo) {
    String mname = fieldInfo.getMethodSuffix();
    JType jType = new XMLInfoNature(fieldInfo).getSchemaType().getJType();

    JMethod[] methods = new JMethod[3];
    methods[0] = makeGetMethod(fieldInfo, mname, jType); // -- create get method
    methods[1] = makeSetMethod(fieldInfo, mname, jType); // -- create set method
    methods[2] = makeGetReferenceIdMethod(fieldInfo); // -- create getReferenceId
    // (from Referable Interface)

    return methods;
  } // -- createAccessMethods

  /**
   * Creates the getter method.
   * 
   * @param fieldInfo the fieldInfo to translate
   * @param mname the name of this field
   * @param jType the type of this field
   * @return the getter method for this identity
   */
  private JMethod makeGetMethod(final FieldInfo fieldInfo, final String mname, final JType jType) {
    JMethod method = new JMethod("get" + mname, jType, "the value of field '" + mname + "'.");
    JSourceCode jsc = method.getSourceCode();
    jsc.add("return this.");
    jsc.append(fieldInfo.getName());
    jsc.append(";");
    return method;
  }

  /**
   * Creates the setter method.
   * 
   * @param fieldInfo the fieldInfo to translate
   * @param mname the name of this field
   * @param jType the type of this field
   * @return the setter method for this identity
   */
  private JMethod makeSetMethod(final FieldInfo fieldInfo, final String mname, final JType jType) {
    JMethod method = new JMethod("set" + mname);
    method.addParameter(new JParameter(jType, fieldInfo.getName()));
    JSourceCode jsc = method.getSourceCode();
    jsc.add("this.");
    jsc.append(fieldInfo.getName());
    jsc.append(" = ");
    jsc.append(fieldInfo.getName());
    jsc.append(";");

    // -- add resolver registration
    // jsc.add("if (idResolver != null) ");
    // jsc.indent();
    // jsc.add("idResolver.addResolvable(");
    // jsc.append(fieldInfo.getName());
    // jsc.append(", this);");
    // jsc.unindent();

    return method;
  }

  /**
   * Creates the getReferenceId method.
   * 
   * @param fieldInfo the fieldInfo to translate
   * @return the getReferenceId method.
   */
  private JMethod makeGetReferenceIdMethod(final FieldInfo fieldInfo) {
    JMethod method = new JMethod("getReferenceId", SGTypes.STRING, "the reference ID");
    JSourceCode jsc = method.getSourceCode();
    jsc.add("return this.");
    jsc.append(fieldInfo.getName());
    jsc.append(";");
    return method;
  }


}
