/**
   * Sets the property to be writable
   *
   * @param mode New Mode {@link PropertPattern#READ_WRITE READ_WRITE}, {@link
   *     PropertPattern#READ_ONLY READ_ONLY} or {@link PropertPattern#WRITE_ONLY WRITE_ONLY}
   * @throws SourceException If the modification of source code is impossible.
   */
  public void setMode(int mode) throws SourceException {
    if (getMode() == mode) return;

    switch (mode) {
      case READ_WRITE:
        if (getterMethod == null) generateGetterMethod();
        if (setterMethod == null) generateSetterMethod();
        if (indexedGetterMethod == null) generateIndexedGetterMethod();
        if (indexedSetterMethod == null) generateIndexedSetterMethod();
        break;
      case READ_ONLY:
        if (getterMethod == null) generateGetterMethod();
        if (indexedGetterMethod == null) generateIndexedGetterMethod();
        if (setterMethod != null) deleteSetterMethod();
        if (indexedSetterMethod != null) deleteIndexedSetterMethod();
        break;
      case WRITE_ONLY:
        if (setterMethod == null) generateSetterMethod();
        if (indexedSetterMethod == null) generateIndexedSetterMethod();
        if (getterMethod != null) deleteGetterMethod();
        if (indexedGetterMethod != null) deleteIndexedGetterMethod();
        break;
    }
  }
  /**
   * Creates new IdxPropertyPattern.
   *
   * @param patternAnalyser patternAnalyser which creates this Property.
   * @param name Name of the Property.
   * @param type Type of the Property ( i.e. Array or Collection )
   * @param indexedType Indexed type of the property.
   * @throws SourceException If the Property can't be created in the source.
   * @return Newly created IdxPropertyPattern.
   */
  static IdxPropertyPattern create(
      PatternAnalyser patternAnalyser, String name, String type, String indexedType)
      throws SourceException {

    IdxPropertyPattern ipp = new IdxPropertyPattern(patternAnalyser);

    ipp.name = name;
    ipp.type = Type.parse(type);
    ipp.indexedType = Type.parse(indexedType);

    ipp.generateGetterMethod();
    ipp.generateSetterMethod();
    ipp.generateIndexedGetterMethod();
    ipp.generateIndexedSetterMethod();

    return ipp;
  }
  /**
   * Sets the non-indexed type of IdxPropertyPattern
   *
   * @param type New non-indexed type of the indexed property
   * @throws SourceException If the modification of source code is impossible
   */
  public void setType(Type type) throws SourceException {

    if (this.type != null && this.type.compareTo(type, true)) return;

    // Remember the old type & old indexed type
    Type oldIndexedType = this.indexedType;
    Type oldType = this.type;

    if (oldType == null) {
      this.type = type;
      oldType = type;
      int mode = getMode();
      if (mode == READ_WRITE || mode == READ_ONLY) generateGetterMethod();
      if (mode == READ_WRITE || mode == WRITE_ONLY) generateSetterMethod();
    } else
      // Change the type
      super.setType(type);

    // Test if the idexedType is the type of array and change it if so
    if (type.isArray()
        && oldType.isArray()
        && oldType.getElementType().compareTo(oldIndexedType, false)) {
      Type newType = type.getElementType();

      if (indexedGetterMethod != null) {
        indexedGetterMethod.setReturn(newType);
      }
      if (indexedSetterMethod != null) {
        MethodParameter[] params = indexedSetterMethod.getParameters();
        if (params.length > 1) {
          params[1].setType(newType);
          indexedSetterMethod.setParameters(params);
        }
      }

      // Set the type  to new type
      setIndexedType(newType);
    }
  }
  /**
   * Creates new indexed property pattern with extended options
   *
   * @param patternAnalyser patternAnalyser which creates this Property.
   * @param name Name of the Property.
   * @param type Type of the Property.
   * @param mode {@link #READ_WRITE Mode} of the new property.
   * @param bound Is the Property bound?
   * @param constrained Is the property constrained?
   * @param withField Should be the private field for this property genareted?
   * @param withReturn Generate return statement in getter?
   * @param withSet Generate seter statement for private field in setter.
   * @param withSupport Generate PropertyChange support?
   * @param niGetter Non-indexed getter method
   * @param niWithReturn Generate return statement in non-indexed getter?
   * @param niSetter Non-indexed setter method
   * @param niWithSet Generate set field statement in non-indexed setter?
   * @throws SourceException If the Property can't be created in the source.
   * @return Newly created PropertyPattern.
   */
  static IdxPropertyPattern create(
      PatternAnalyser patternAnalyser,
      String name,
      String type,
      int mode,
      boolean bound,
      boolean constrained,
      boolean withField,
      boolean withReturn,
      boolean withSet,
      boolean withSupport,
      boolean niGetter,
      boolean niWithReturn,
      boolean niSetter,
      boolean niWithSet)
      throws SourceException {

    IdxPropertyPattern ipp = new IdxPropertyPattern(patternAnalyser);

    ipp.name = name;
    ipp.type = null;
    ipp.indexedType = Type.parse(type);

    // Set the non-indexed type when needed
    if (withField || withSupport || niGetter || niSetter) {
      ipp.type = Type.createArray(ipp.indexedType);
    }

    // Generate field
    if (withField || withSupport) {
      if (ipp.type != null) ipp.generateField(true);
    }

    // Ensure property change support field and methods exist
    String supportName = null;
    String vetoSupportName = null;

    if (withSupport) {
      if (bound) supportName = BeanPatternGenerator.supportField(ipp.getDeclaringClass());
      if (constrained)
        vetoSupportName = BeanPatternGenerator.vetoSupportField(ipp.getDeclaringClass());

      if (bound) BeanPatternGenerator.supportListenerMethods(ipp.getDeclaringClass(), supportName);
      if (constrained)
        BeanPatternGenerator.vetoSupportListenerMethods(ipp.getDeclaringClass(), vetoSupportName);
    }

    if (mode == READ_WRITE || mode == READ_ONLY) {
      ipp.generateIndexedGetterMethod(
          BeanPatternGenerator.idxPropertyGetterBody(name, withReturn), true);
      if (ipp.type != null && niGetter)
        ipp.generateGetterMethod(BeanPatternGenerator.propertyGetterBody(name, niWithReturn), true);
    }
    if (mode == READ_WRITE || mode == WRITE_ONLY) {
      /*
      ipp.generateIndexedSetterMethod( BeanPatternGenerator.idxPropertySetterBody( name, ipp.getType(),
          bound, constrained, withSet, withSupport, supportName, vetoSupportName ), constrained, true );
      */
      ipp.generateIndexedSetterMethod(
          BeanPatternGenerator.idxPropertySetterBody(
              name,
              ipp.getIndexedType(),
              bound,
              constrained,
              withSet,
              withSupport,
              supportName,
              vetoSupportName),
          constrained,
          true);

      if (ipp.type != null && niSetter)
        ipp.generateSetterMethod(
            BeanPatternGenerator.propertySetterBody(
                name,
                ipp.getType(),
                bound,
                constrained,
                niWithSet,
                withSupport,
                supportName,
                vetoSupportName),
            constrained,
            true);
    }
    return ipp;
  }