/**
   * This method performs the morphology for adverbs.
   *
   * @param element the <code>InflectedWordElement</code>.
   * @param baseWord the <code>WordElement</code> as created from the lexicon entry.
   * @return a <code>StringElement</code> representing the word after inflection.
   */
  public NLGElement doAdverbMorphology(InflectedWordElement element, WordElement baseWord) {

    String realised = null;

    // base form from baseWord if it exists, otherwise from element
    String baseForm = getBaseForm(element, baseWord);

    if (element.getFeatureAsBoolean(Feature.IS_COMPARATIVE).booleanValue()) {
      realised = element.getFeatureAsString(LexicalFeature.COMPARATIVE);

      if (realised == null && baseWord != null) {
        realised = baseWord.getFeatureAsString(LexicalFeature.COMPARATIVE);
      }
      if (realised == null) {
        realised = buildRegularComparative(baseForm);
      }
    } else if (element.getFeatureAsBoolean(Feature.IS_SUPERLATIVE).booleanValue()) {

      realised = element.getFeatureAsString(LexicalFeature.SUPERLATIVE);

      if (realised == null && baseWord != null) {
        realised = baseWord.getFeatureAsString(LexicalFeature.SUPERLATIVE);
      }
      if (realised == null) {
        realised = buildRegularSuperlative(baseForm);
      }
    } else {
      realised = baseForm;
    }
    // vaudrypl added element as 2nd argument
    StringElement realisedElement = new StringElement(realised, element);
    realisedElement.setFeature(
        InternalFeature.DISCOURSE_FUNCTION, element.getFeature(InternalFeature.DISCOURSE_FUNCTION));
    return realisedElement;
  }
  /**
   * 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;
  }
  /**
   * This method performs the morphology for nouns.
   *
   * @param element the <code>InflectedWordElement</code>.
   * @param baseWord the <code>WordElement</code> as created from the lexicon entry.
   * @return a <code>StringElement</code> representing the word after inflection.
   */
  public StringElement doNounMorphology(InflectedWordElement element, WordElement baseWord) {
    StringBuffer realised = new StringBuffer();

    // base form from baseWord if it exists, otherwise from element
    String baseForm = getBaseForm(element, baseWord);

    if (element.isPlural() && !element.getFeatureAsBoolean(LexicalFeature.PROPER).booleanValue()) {

      String pluralForm = null;

      // AG changed: now check if default infl is uncount
      // if (element.getFeatureAsBoolean(LexicalFeature.NON_COUNT)
      // .booleanValue()) {
      // pluralForm = baseForm;
      String elementDefaultInfl = element.getFeatureAsString(LexicalFeature.DEFAULT_INFL);
      if (elementDefaultInfl != null && elementDefaultInfl.equals("uncount")) {
        pluralForm = baseForm;
      } else {
        pluralForm = element.getFeatureAsString(LexicalFeature.PLURAL);
      }

      if (pluralForm == null && baseWord != null) {
        // AG changed: now check if default infl is uncount
        // if (baseWord.getFeatureAsBoolean(LexicalFeature.NON_COUNT)
        // .booleanValue()) {
        // pluralForm = baseForm;
        String baseDefaultInfl = baseWord.getFeatureAsString(LexicalFeature.DEFAULT_INFL);
        if (baseDefaultInfl != null && baseDefaultInfl.equals("uncount")) {
          pluralForm = baseForm;
        } else {
          pluralForm = baseWord.getFeatureAsString(LexicalFeature.PLURAL);
        }
      }

      if (pluralForm == null) {
        Object pattern = element.getFeature(Feature.PATTERN);
        if (Pattern.GRECO_LATIN_REGULAR.equals(pattern)) {
          pluralForm = buildGrecoLatinPluralNoun(baseForm);
        } else {
          pluralForm = buildRegularPluralNoun(baseForm);
        }
      }
      realised.append(pluralForm);

    } else {
      realised.append(baseForm);
    }

    checkPossessive(element, realised);
    // vaudrypl added element as 2nd argument
    StringElement realisedElement = new StringElement(realised.toString(), element);
    realisedElement.setFeature(
        InternalFeature.DISCOURSE_FUNCTION, element.getFeature(InternalFeature.DISCOURSE_FUNCTION));
    return realisedElement;
  }
 /**
  * This method performs the morphology for determiners. Modified from the same method in the
  * simplenlg.morphology.english.MorphologyRules class.
  *
  * @param element the <code>InflectedWordElement</code>.
  * @author vaudrypl
  */
 public NLGElement doDeterminerMorphology(InflectedWordElement element) {
   String inflectedForm = element.getBaseForm();
   if (inflectedForm.equals("a")) {
     if (element.isPlural()) {
       inflectedForm = "some";
       //			} else {
       //				WordElement nextWord = (WordElement)
       // element.getParent().getFeature(InternalFeature.HEAD);
       //				if (nextWord.getRealisation().matches("\\A(a|e|i|o|u).*")) { //$NON-NLS-1$
       //					element.setRealisation("an"); //$NON-NLS-1$
       //				}
     }
   }
   // vaudrypl added element as 2nd argument
   StringElement realisedElement = new StringElement(inflectedForm, element);
   realisedElement.setFeature(
       InternalFeature.DISCOURSE_FUNCTION, element.getFeature(InternalFeature.DISCOURSE_FUNCTION));
   return realisedElement;
 }
  /**
   * This method performs the morphology for verbs.
   *
   * @param element the <code>InflectedWordElement</code>.
   * @param baseWord the <code>WordElement</code> as created from the lexicon entry.
   * @return a <code>StringElement</code> representing the word after inflection.
   */
  public NLGElement doVerbMorphology(InflectedWordElement element, WordElement baseWord) {

    String realised = null;
    Object numberValue = element.getFeature(Feature.NUMBER);
    Object personValue = element.getFeature(Feature.PERSON);
    Object tenseValue = element.getFeature(Feature.TENSE);
    Object formValue = element.getFeature(Feature.FORM);
    Object patternValue = element.getFeature(Feature.PATTERN);

    // base form from baseWord if it exists, otherwise from element
    String baseForm = getBaseForm(element, baseWord);

    if (element.isNegated() || Form.BARE_INFINITIVE.equals(formValue)) {
      realised = baseForm;
    } else if (Form.PRESENT_PARTICIPLE.equals(formValue)) {
      realised = element.getFeatureAsString(LexicalFeature.PRESENT_PARTICIPLE);

      if (realised == null && baseWord != null) {
        realised = baseWord.getFeatureAsString(LexicalFeature.PRESENT_PARTICIPLE);
      }
      if (realised == null) {
        if (Pattern.REGULAR_DOUBLE.equals(patternValue)) {
          realised = buildDoublePresPartVerb(baseForm);
        } else {
          realised = buildRegularPresPartVerb(baseForm);
        }
      }
    } else if (Tense.PAST.equals(tenseValue) || Form.PAST_PARTICIPLE.equals(formValue)) {
      if (Form.PAST_PARTICIPLE.equals(formValue)) {
        realised = element.getFeatureAsString(LexicalFeature.PAST_PARTICIPLE);

        if (realised == null && baseWord != null) {
          realised = baseWord.getFeatureAsString(LexicalFeature.PAST_PARTICIPLE);
        }
        if (realised == null) {
          if ("be".equalsIgnoreCase(baseForm)) { // $NON-NLS-1$
            realised = "been"; // $NON-NLS-1$
          } else if (Pattern.REGULAR_DOUBLE.equals(patternValue)) {
            realised = buildDoublePastVerb(baseForm);
          } else {
            realised = buildRegularPastVerb(baseForm, numberValue);
          }
        }
      } else {
        realised = element.getFeatureAsString(LexicalFeature.PAST);

        if (realised == null && baseWord != null) {
          realised = baseWord.getFeatureAsString(LexicalFeature.PAST);
        }
        if (realised == null) {
          if (Pattern.REGULAR_DOUBLE.equals(patternValue)) {
            realised = buildDoublePastVerb(baseForm);
          } else {
            realised = buildRegularPastVerb(baseForm, numberValue);
          }
        }
      }
    } else if ((numberValue == null || NumberAgreement.SINGULAR.equals(numberValue))
        && (personValue == null || Person.THIRD.equals(personValue))
        && (tenseValue == null || Tense.PRESENT.equals(tenseValue))) {

      realised = element.getFeatureAsString(LexicalFeature.PRESENT3S);

      if (realised == null && baseWord != null && !"be".equalsIgnoreCase(baseForm)) { // $NON-NLS-1$
        realised = baseWord.getFeatureAsString(LexicalFeature.PRESENT3S);
      }
      if (realised == null) {
        realised = buildPresent3SVerb(baseForm);
      }
    } else {
      if ("be".equalsIgnoreCase(baseForm)) { // $NON-NLS-1$
        if (Person.FIRST.equals(personValue)
            && (NumberAgreement.SINGULAR.equals(numberValue) || numberValue == null)) {
          realised = "am"; // $NON-NLS-1$
        } else {
          realised = "are"; // $NON-NLS-1$
        }
      } else {
        realised = baseForm;
      }
    }
    // vaudrypl added element as 2nd argument
    StringElement realisedElement = new StringElement(realised, element);
    realisedElement.setFeature(
        InternalFeature.DISCOURSE_FUNCTION, element.getFeature(InternalFeature.DISCOURSE_FUNCTION));
    return realisedElement;
  }