/**
         * Applies aggregation to two NLGElements e1 and e2, succeeding only if they
         * are clauses (that is, e1.getCategory() == e2.getCategory ==
         * {@link simplenlg.framework.PhraseCategory#CLAUSE}).
         */
        public override NLGElement apply(NLGElement previous, NLGElement next)
        {
            NLGElement aggregated = null;

            if (previous.Category == PhraseCategory.PhraseCategoryEnum.CLAUSE && next.Category == PhraseCategory.PhraseCategoryEnum.CLAUSE && PhraseChecker.nonePassive(previous, next) && !PhraseChecker.expletiveSubjects(previous, next))
            {
                if (PhraseChecker.sameSentences(previous, next))
                {                 // case 1: identical sentences: remove the current
                    aggregated = previous;
                }
                else if (PhraseChecker.sameFrontMods(previous, next) && PhraseChecker.sameSubjects(previous, next) && PhraseChecker.samePostMods(previous, next))
                {                 // case 2: subjects identical: coordinate VPs
                    aggregated = factory.createClause();
                    aggregated.setFeature(InternalFeature.SUBJECTS, previous.getFeatureAsElementList(InternalFeature.SUBJECTS));
                    aggregated.setFeature(InternalFeature.FRONT_MODIFIERS, previous.getFeatureAsElement(InternalFeature.FRONT_MODIFIERS));
                    aggregated.setFeature(Feature.CUE_PHRASE, previous.getFeatureAsElement(Feature.CUE_PHRASE));
                    aggregated.setFeature(InternalFeature.POSTMODIFIERS, previous.getFeatureAsElementList(InternalFeature.POSTMODIFIERS));
                    NLGElement vp;

                    if (!PhraseChecker.sameVPArgs(previous, next) && PhraseChecker.sameVPHead(previous, next) && PhraseChecker.sameVPModifiers(previous, next))
                    {                     // case 2.1: VPs have different arguments but same head & mods
                        NLGElement vp1 = previous.getFeatureAsElement(InternalFeature.VERB_PHRASE);
                        vp = factory.createVerbPhrase();
                        vp.setFeature(InternalFeature.HEAD, vp1.getFeatureAsElement(InternalFeature.HEAD));
                        vp.setFeature(InternalFeature.COMPLEMENTS, vp1.getFeatureAsElementList(InternalFeature.COMPLEMENTS));
                        vp.setFeature(InternalFeature.PREMODIFIERS, vp1.getFeatureAsElementList(InternalFeature.PREMODIFIERS));
                        vp.setFeature(InternalFeature.POSTMODIFIERS, vp1.getFeatureAsElementList(InternalFeature.POSTMODIFIERS));
                    }
                    else
                    {                     // case 2.2: just create a coordinate vP
                        NLGElement vp1 = previous.getFeatureAsElement(InternalFeature.VERB_PHRASE);
                        NLGElement vp2 = next.getFeatureAsElement(InternalFeature.VERB_PHRASE);
                        vp = factory.createCoordinatedPhrase(vp1, vp2);
                    }
                    // case 2.3: expletive subjects
                    aggregated.setFeature(InternalFeature.VERB_PHRASE, vp);
                }
                else if (PhraseChecker.sameFrontMods(previous, next) && PhraseChecker.sameVP(previous, next) && PhraseChecker.samePostMods(previous, next))
                {                 // case 3: identical VPs: conjoin subjects and front modifiers
                    aggregated = factory.createClause();
                    aggregated.setFeature(InternalFeature.FRONT_MODIFIERS, previous.getFeatureAsElementList(InternalFeature.FRONT_MODIFIERS));
                    CoordinatedPhraseElement subjects = factory.createCoordinatedPhrase();
                    subjects.Category = new PhraseCategory(PhraseCategory.PhraseCategoryEnum.NOUN_PHRASE);
                    IList <NLGElement> allSubjects = previous.getFeatureAsElementList(InternalFeature.SUBJECTS);
                    ((List <NLGElement>)allSubjects).AddRange(next.getFeatureAsElementList(InternalFeature.SUBJECTS));

                    foreach (NLGElement subj in allSubjects)
                    {
                        subjects.addCoordinate(subj);
                    }

                    aggregated.setFeature(InternalFeature.SUBJECTS, subjects);
                    aggregated.setFeature(InternalFeature.POSTMODIFIERS, previous.getFeatureAsElementList(InternalFeature.POSTMODIFIERS));
                    aggregated.setFeature(InternalFeature.VERB_PHRASE, previous.getFeature(InternalFeature.VERB_PHRASE));
                }
            }

            return(aggregated);
        }
        /**
         * Applies backward conjunction reduction to two NLGElements e1 and e2,
         * succeeding only if they are clauses (that is, e1.getCategory() ==
         * e2.getCategory == {@link simplenlg.framework.PhraseCategory#CLAUSE}).
         *
         * @param previous
         *            the first phrase
         * @param next
         *            the second phrase
         * @return a coordinate phrase if aggregation is successful,
         *         <code>null</code> otherwise
         */
        public override NLGElement apply(NLGElement previous, NLGElement next)
        {
            bool success = false;

            if (previous.Category == PhraseCategory.PhraseCategoryEnum.CLAUSE && next.Category == PhraseCategory.PhraseCategoryEnum.CLAUSE && PhraseChecker.nonePassive(previous, next))
            {
                IList <PhraseSet> rightPeriphery = PhraseChecker.rightPeriphery(previous, next);

                foreach (PhraseSet pair in rightPeriphery)
                {
                    if (pair.lemmaIdentical())
                    {
                        pair.elideLeftmost();
                        success = true;
                    }
                }
            }

            return(success ? factory.createCoordinatedPhrase(previous, next) : null);
        }