/**
         * This is the main method for performing the morphology. It effectively
         * examines the lexical category of the element and calls the relevant set
         * of rules from <code>MorphologyRules</em>.
         *
         * @param element
         *            the <code>InflectedWordElement</code>
         * @return an <code>NLGElement</code> reflecting the correct inflection for
         *         the word.
         */
        private NLGElement doMorphology(InflectedWordElement element)
        {
            NLGElement realisedElement = null;

            if (element.getFeatureAsBoolean(InternalFeature.NON_MORPH))
            {
                realisedElement = new StringElement(element.BaseForm);
                realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION, element.getFeature(InternalFeature.DISCOURSE_FUNCTION));
            }
            else
            {
                NLGElement baseWord = element.getFeatureAsElement(InternalFeature.BASE_WORD);

                if (baseWord == null && lexicon != null)
                {
                    baseWord = lexicon.lookupWord(element.BaseForm);
                }

                ElementCategory category = element.Category;

                if (category is LexicalCategory)
                {
                    switch (((LexicalCategory)category).GetLexicalCategory())
                    {
                    case LexicalCategory.LexicalCategoryEnum.PRONOUN:
                        realisedElement = MorphologyRules.doPronounMorphology(element);
                        break;

                    case LexicalCategory.LexicalCategoryEnum.NOUN:
                        realisedElement = MorphologyRules.doNounMorphology(element, (WordElement)baseWord);
                        break;

                    case LexicalCategory.LexicalCategoryEnum.VERB:
                        realisedElement = MorphologyRules.doVerbMorphology(element, (WordElement)baseWord);
                        break;

                    case LexicalCategory.LexicalCategoryEnum.ADJECTIVE:
                        realisedElement = MorphologyRules.doAdjectiveMorphology(element, (WordElement)baseWord);
                        break;

                    case LexicalCategory.LexicalCategoryEnum.ADVERB:
                        realisedElement = MorphologyRules.doAdverbMorphology(element, (WordElement)baseWord);
                        break;

                    default:
                        realisedElement = new StringElement(element.BaseForm);
                        realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION, element.getFeature(InternalFeature.DISCOURSE_FUNCTION));
                        break;
                    }
                }
            }
            return(realisedElement);
        }
        public override IList <NLGElement> realise(IList <NLGElement> elements)
        {
            IList <NLGElement> realisedElements = new List <NLGElement>();
            NLGElement         currentElement   = null;
            NLGElement         determiner       = null;
            NLGElement         prevElement      = null;

            if (elements != null)
            {
                foreach (NLGElement eachElement in elements)
                {
                    currentElement = realise(eachElement);

                    if (currentElement != null)
                    {
                        //pass the discourse function and appositive features -- important for orth processor
                        currentElement.setFeature(Feature.APPOSITIVE, eachElement.getFeature(Feature.APPOSITIVE));
                        object function = eachElement.getFeature(InternalFeature.DISCOURSE_FUNCTION);

                        if (function != null)
                        {
                            currentElement.setFeature(InternalFeature.DISCOURSE_FUNCTION, function);
                        }

                        if (prevElement != null && prevElement is StringElement && eachElement is InflectedWordElement && ((InflectedWordElement)eachElement).Category == LexicalCategory.LexicalCategoryEnum.NOUN)
                        {
                            string prevString = prevElement.Realisation;

                            //realisedElements.get(realisedElements.size() - 1)

                            prevElement.Realisation = DeterminerAgrHelper.checkEndsWithIndefiniteArticle(prevString, currentElement.Realisation);
                        }

                        // realisedElements.add(realise(currentElement));
                        realisedElements.Add(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 is ListElement)
                            {
                                // list elements: ensure det matches first element
                                NLGElement firstChild = ((ListElement)currentElement).Children[0];

                                if (firstChild != null)
                                {
                                    //AG: need to check if child is a coordinate
                                    if (firstChild is CoordinatedPhraseElement)
                                    {
                                        MorphologyRules.doDeterminerMorphology(determiner, firstChild.Children[0].Realisation);
                                    }
                                    else
                                    {
                                        MorphologyRules.doDeterminerMorphology(determiner, firstChild.Realisation);
                                    }
                                }
                            }
                            else
                            {
                                // everything else: ensure det matches realisation
                                MorphologyRules.doDeterminerMorphology(determiner, currentElement.Realisation);
                            }

                            determiner = null;
                        }
                    }
                    prevElement = eachElement;
                }
            }

            return(realisedElements);
        }