/**
   * This method performs the morphology for pronouns.
   *
   * @param element the <code>InflectedWordElement</code>.
   * @return a <code>StringElement</code> representing the word after inflection.
   */
  public NLGElement doPronounMorphology(InflectedWordElement element) {
    String realised = null;

    if (!element.getFeatureAsBoolean(InternalFeature.NON_MORPH).booleanValue()) {
      Object genderValue = element.getFeature(LexicalFeature.GENDER);
      Object personValue = element.getFeature(Feature.PERSON);

      // way of getting discourseValue changed by vaudrypl
      NLGElement parent = element.getParent();
      Object discourseValue = element.getFeature(InternalFeature.DISCOURSE_FUNCTION);
      if (discourseValue == DiscourseFunction.SUBJECT
          && parent != null
          && parent.isA(PhraseCategory.NOUN_PHRASE)) {
        discourseValue = parent.getFeature(InternalFeature.DISCOURSE_FUNCTION);
      }
      if (!(discourseValue instanceof DiscourseFunction))
        discourseValue = DiscourseFunction.SUBJECT;

      int numberIndex = element.isPlural() ? 1 : 0;
      int genderIndex = (genderValue instanceof Gender) ? ((Gender) genderValue).ordinal() : 2;

      int personIndex = (personValue instanceof Person) ? ((Person) personValue).ordinal() : 2;

      if (personIndex == 2) {
        personIndex += genderIndex;
      }

      int positionIndex = 0;

      if (element.getFeatureAsBoolean(LexicalFeature.REFLEXIVE).booleanValue()) {
        positionIndex = 2;
      } else if (element.getFeatureAsBoolean(Feature.POSSESSIVE).booleanValue()) {
        positionIndex = 3;
        if (DiscourseFunction.SPECIFIER.equals(discourseValue)) {
          positionIndex++;
        }
      } else {
        positionIndex =
            (DiscourseFunction.SUBJECT.equals(discourseValue)
                        && !element.getFeatureAsBoolean(Feature.PASSIVE).booleanValue())
                    || (DiscourseFunction.OBJECT.equals(discourseValue)
                        && element.getFeatureAsBoolean(Feature.PASSIVE).booleanValue())
                    || DiscourseFunction.SPECIFIER.equals(discourseValue)
                    || (DiscourseFunction.COMPLEMENT.equals(discourseValue)
                        && element.getFeatureAsBoolean(Feature.PASSIVE).booleanValue())
                ? 0
                : 1;
      }
      realised = PRONOUNS[numberIndex][positionIndex][personIndex];
    } else {
      realised = element.getBaseForm();
    }
    // vaudrypl added element as 2nd argument
    StringElement realisedElement = new StringElement(realised, element);
    realisedElement.setFeature(
        InternalFeature.DISCOURSE_FUNCTION, element.getFeature(InternalFeature.DISCOURSE_FUNCTION));

    return realisedElement;
  }
  @Override
  public List<NLGElement> realise(List<NLGElement> elements) {
    List<NLGElement> realisedElements = new ArrayList<NLGElement>();
    NLGElement currentElement = null;
    NLGElement determiner = null;

    if (elements != null) {
      for (NLGElement eachElement : elements) {
        currentElement = realise(eachElement);
        if (currentElement != null) {
          realisedElements.add(realise(currentElement));
          if (determiner == null
              && DiscourseFunction.SPECIFIER.equals(
                  currentElement.getFeature(InternalFeature.DISCOURSE_FUNCTION))) {
            determiner = currentElement;
            determiner.setFeature(Feature.NUMBER, eachElement.getFeature(Feature.NUMBER));
            // MorphologyRules.doDeterminerMorphology(determiner,
            // currentElement.getRealisation());
          } else if (determiner != null) {

            if (currentElement instanceof ListElement) {
              NLGElement firstChild = ((ListElement) currentElement).getChildren().get(0);

              if (firstChild != null) {
                MorphologyRules.doDeterminerMorphology(determiner, firstChild.getRealisation());
              }
            } else {
              MorphologyRules.doDeterminerMorphology(determiner, currentElement.getRealisation());
            }

            determiner = null;
          }
        }
      }
    }
    return realisedElements;
  }