All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.force.i18n.grammar.impl.IndoAryanDeclension Maven / Gradle / Ivy

There is a newer version: 1.2.30
Show newest version
/*
 * Copyright (c) 2019, salesforce.com, inc.
 * All rights reserved.
 * Licensed under the BSD 3-Clause license.
 * For full license text, see LICENSE.txt file in the repo root  or https://opensource.org/licenses/BSD-3-Clause
 */
package com.force.i18n.grammar.impl;

import java.util.*;
import java.util.logging.Logger;

import com.force.i18n.HumanLanguage;
import com.force.i18n.grammar.*;
import com.force.i18n.grammar.Noun.NounType;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.*;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

/**
 * Implementation of most Indo-Aryan languages, those with more than 2 cases
 * (unlike Hindustani) and without articles (IndoAryan)
 *
 * As pointed out in the wiki article, there's a popularity in studying German
 * among Marathi native speakers, due to the similarities in the grammar.  Hence
 * the implementation is a lot like an article-less German.
 *
 * @see Wikipedia: Indo-Aryan languages
 * @see Wikipedia: Gujarati Nouns
 * @see Wikipedia: Marathi Nouns
 * @author stamm
 * @since 1.1
 */
abstract class IndoAryanDeclension extends AbstractLanguageDeclension {
    private static final Logger logger = Logger.getLogger(IndoAryanDeclension.class.getName());

    private final List entityForms;
    private final List fieldForms;
    private final List adjectiveForms;
    private final NounFormMap nounFormMap;
    private final ModifierFormMap adjectiveFormMap;

    public IndoAryanDeclension(HumanLanguage language) {
        super(language);
        // Generate the different forms from subclass methods
        ImmutableList.Builder entityBuilder = ImmutableList.builder();
        ImmutableList.Builder fieldBuilder = ImmutableList.builder();
        int ordinal = 0;
        for (LanguageNumber number : getAllowedNumbers()) {
            for (LanguageCase caseType : getRequiredCases()) {
                IndoAryanNounForm form = new IndoAryanNounForm(this, number, caseType, ordinal++);
                entityBuilder.add(form);
                if (caseType == LanguageCase.NOMINATIVE) {
                    fieldBuilder.add(form); // Only plurals count for the fields
                }
            }
        }
        this.entityForms = entityBuilder.build();
        this.fieldForms = fieldBuilder.build();
        this.nounFormMap = new NounFormMap<>(this.entityForms);

        ImmutableList.Builder adjBuilder = ImmutableList.builder();
        int adjOrdinal = 0;
        for (LanguageNumber number : getAllowedNumbers()) {
            for (LanguageGender gender : getRequiredGenders()) {
                for (LanguageCase caseType : getRequiredCases()) {
                    adjBuilder.add(new IndoAryanAdjectiveForm(this, number, gender, caseType, adjOrdinal++));
                }
            }
        }
        this.adjectiveForms = adjBuilder.build();
        this.adjectiveFormMap = new ModifierFormMap<>(this.adjectiveForms);
    }

    static class IndoAryanNounForm extends ComplexNounForm {
        private static final long serialVersionUID = 1L;

        private final LanguageCase caseType;
        private final LanguageNumber number;

        public IndoAryanNounForm(LanguageDeclension declension, LanguageNumber number, LanguageCase caseType, int ordinal) {
            super(declension, ordinal);
            this.number = number;
            this.caseType = caseType;
        }

        @Override public LanguageArticle getArticle() { return LanguageArticle.ZERO; }
        @Override public LanguageCase getCase() {  return this.caseType; }
        @Override public LanguageNumber getNumber() {  return this.number; }
        @Override public LanguagePossessive getPossessive() { return LanguagePossessive.NONE;}

        @Override
        public String getKey() {
            return getNumber().getDbValue() + "-" + getCase().getDbValue();
        }

        @Override
        public int hashCode() {
            return Objects.hash(super.hashCode(), this.caseType, this.number);
        }

        @Override
        public boolean equals(Object other) {
            if (this == other) return true;
            if (other instanceof IndoAryanNounForm) {
                IndoAryanNounForm o = this.getClass().cast(other);
                return super.equals(other) && this.caseType == o.caseType && this.number == o.number;
            }
            return false;
        }

        @Override
        public String toString() {
            return "IndoAryanNF:"+getKey();
        }
    }

    static class IndoAryanAdjectiveForm extends ComplexAdjectiveForm {
        private static final long serialVersionUID = 1L;

        private final LanguageNumber number;
        private final LanguageCase caseType;
        private final LanguageGender gender;

        public IndoAryanAdjectiveForm(LanguageDeclension declension, LanguageNumber number, LanguageGender gender, LanguageCase caseType, int ordinal) {
            super(declension, ordinal);
            this.number = number;
            this.gender = gender;
            this.caseType = caseType;
        }

        @Override public LanguageArticle getArticle() { return LanguageArticle.ZERO; }
        @Override public LanguageCase getCase() {  return this.caseType; }
        @Override public LanguageNumber getNumber() {  return this.number; }
        @Override public LanguageStartsWith getStartsWith() {  return LanguageStartsWith.CONSONANT; }
        @Override public LanguageGender getGender() {  return this.gender; }
        @Override public LanguagePossessive getPossessive() { return LanguagePossessive.NONE; }
        @Override
        public String getKey() {
            return getGender().getDbValue() + "-" + getNumber().getDbValue() + "-" + getCase().getDbValue();
        }

        @Override
        public int hashCode() {
            return Objects.hash(super.hashCode(), this.number, this.caseType, this.gender);
        }

        @Override
        public boolean equals(Object other) {
            if (this == other) return true;
            if (other instanceof IndoAryanAdjectiveForm) {
                IndoAryanAdjectiveForm o = this.getClass().cast(other);
                return super.equals(other) && this.number == o.number && this.caseType == o.caseType
                        && this.gender == o.gender;
            }
            return false;
        }
    }

    /**
     * Represents an IndoAryan noun.
     * See IndoAryanNounForm for more info
     */
    public static class IndoAryanNoun extends ComplexNoun {
        private static final long serialVersionUID = 1L;

        IndoAryanNoun(IndoAryanDeclension declension, String name, String pluralAlias, NounType type, String entityName, LanguageGender gender, String access, boolean isStandardField, boolean isCopiedFromDefault) {
            super(declension, name, pluralAlias, type, entityName, LanguageStartsWith.CONSONANT, gender, access, isStandardField, isCopiedFromDefault);
        }

        @Override
        protected boolean validateValues(String name, LanguageCase _case) {
            return defaultValidate(name, getDeclension().getFieldForms());
        }

        @Override
        protected final Class getFormClass() {
            return IndoAryanNounForm.class;
        }

        @Override
        protected boolean validateGender(String name) {
            if (!getDeclension().getRequiredGenders().contains(getGender())) {
                logger.info(VALIDATION_WARNING_HEADER + name + " invalid gender");
                setGender(getDeclension().getDefaultGender());
            }
            return true;
        }
    }

    /**
     * Represents an Indo-Aryan adjective
     */
    public static class IndoAryanAdjective extends ComplexAdjective {
        private static final long serialVersionUID = 1L;

        IndoAryanAdjective(LanguageDeclension declension, String name, LanguagePosition position) {
            super(declension, name, position);
        }

        @Override
        protected final Class getFormClass() {
            return IndoAryanAdjectiveForm.class;
        }

        @Override
        public boolean validate(String name) {
            defaultValidate(name, ImmutableSet.of(getDeclension().getAdjectiveForm(LanguageStartsWith.CONSONANT, LanguageGender.NEUTER, LanguageNumber.SINGULAR, LanguageCase.NOMINATIVE, LanguageArticle.ZERO, LanguagePossessive.NONE)));
            return true;
        }
    }

    @Override
    public Adjective createAdjective(String name, LanguageStartsWith startsWith, LanguagePosition position) {
        return new IndoAryanAdjective(this, name, position);
    }

    @Override
    public Noun createNoun(String name, String pluralAlias, NounType type, String entityName, LanguageStartsWith startsWith, LanguageGender gender, String access, boolean isStandardField, boolean isCopied) {
        return new IndoAryanNoun(this, name, pluralAlias, type, entityName, gender, access, isStandardField, isCopied);
    }

    @Override
    public List getAdjectiveForms() {
        return this.adjectiveForms;
    }

    @Override
    public List< ? extends NounForm> getAllNounForms() {
        return this.entityForms;
    }

    @Override
    public Collection< ? extends NounForm> getEntityForms() {
        return this.entityForms;
    }

    @Override
    public Collection< ? extends NounForm> getFieldForms() {
        return this.fieldForms;
    }

    @Override
    public Collection< ? extends NounForm> getOtherForms() {
        return Collections.singleton(fieldForms.get(0));  // Only need "singular" for other forms
    }

    @Override
    public AdjectiveForm getAdjectiveForm(LanguageStartsWith startsWith, LanguageGender gender, LanguageNumber number,
            LanguageCase _case, LanguageArticle article, LanguagePossessive possessive) {
        return this.adjectiveFormMap.getForm(startsWith, gender, number, _case);
    }

    @Override
    public NounForm getExactNounForm(LanguageNumber number, LanguageCase _case, LanguagePossessive possessive,
            LanguageArticle article) {
        if (possessive != LanguagePossessive.NONE) return null;
        return this.nounFormMap.getForm(number, _case);
    }

    @Override
    public LanguageGender getDefaultGender() {
        return LanguageGender.MASCULINE;
    }

    @Override
    public boolean hasGender() {
        return true;
    }

    @Override
    public boolean hasStartsWith() {
        return false;
    }

    @Override
    public EnumSet getRequiredGenders() {
        return EnumSet.of(LanguageGender.NEUTER, LanguageGender.FEMININE, LanguageGender.MASCULINE);
    }

    static final class GujaratiDeclension extends IndoAryanDeclension {
        public GujaratiDeclension(HumanLanguage language) {
            super(language);
        }

        @Override
        public EnumSet getRequiredCases() {
            return EnumSet.of(LanguageCase.NOMINATIVE, LanguageCase.OBJECTIVE, LanguageCase.LOCATIVE);  // TODO: Locative is questionable.
        }
    }

    static final class MarathiDeclension extends IndoAryanDeclension {
        public MarathiDeclension(HumanLanguage language) {
            super(language);
        }

        // https://en.wikipedia.org/wiki/Marathi_grammar#Nominals
        // This needs more study.  In the meantime, I'm making it too many
        @Override
        public EnumSet getRequiredCases() {
            return EnumSet.of(LanguageCase.NOMINATIVE, LanguageCase.ACCUSATIVE, LanguageCase.INSTRUMENTAL, LanguageCase.DATIVE, LanguageCase.ABLATIVE, LanguageCase.GENITIVE, LanguageCase.LOCATIVE);
        }
    }

    // https://en.wikipedia.org/wiki/Punjabi_grammar
    // Nominitive = direct
    // Accusative = oblique
    static final class PunjabiDeclension extends IndoAryanDeclension {
        public PunjabiDeclension(HumanLanguage language) {
            super(language);
        }

        @Override
        public EnumSet getRequiredCases() {
            return EnumSet.of(LanguageCase.NOMINATIVE, LanguageCase.ACCUSATIVE, LanguageCase.INSTRUMENTAL, LanguageCase.ABLATIVE, LanguageCase.VOCATIVE);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy