/** * Copyright 2016 * Ubiquitous Knowledge Processing (UKP) Lab * Technische Universität Darmstadt * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.tudarmstadt.ukp.lmf.transform.germanet; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import de.tudarmstadt.ukp.lmf.model.core.Definition; import de.tudarmstadt.ukp.lmf.model.core.Sense; import de.tudarmstadt.ukp.lmf.model.core.TextRepresentation; import de.tudarmstadt.ukp.lmf.model.enums.ELabelTypeSemantics; import de.tudarmstadt.ukp.lmf.model.enums.ELanguageIdentifier; import de.tudarmstadt.ukp.lmf.model.enums.ERelNameSemantics; import de.tudarmstadt.ukp.lmf.model.enums.ERelTypeSemantics; import de.tudarmstadt.ukp.lmf.model.meta.SemanticLabel; import de.tudarmstadt.ukp.lmf.model.semantics.MonolingualExternalRef; import de.tudarmstadt.ukp.lmf.model.semantics.SenseExample; import de.tudarmstadt.ukp.lmf.model.semantics.SenseRelation; import de.tuebingen.uni.sfs.germanet.api.ConRel; import de.tuebingen.uni.sfs.germanet.api.GermaNet; import de.tuebingen.uni.sfs.germanet.api.LexRel; import de.tuebingen.uni.sfs.germanet.api.LexUnit; import de.tuebingen.uni.sfs.germanet.api.Synset; import de.tuebingen.uni.sfs.germanet.api.WiktionaryParaphrase; /** * This class offers methods for generating instances of {@link Sense} class from * <a href="URL#http://www.sfs.uni-tuebingen.de/lsd/index.shtml">GermaNet 7.0</a> * @author Zijad Maksuti * @author Judith Eckle-Kohler * */ public class SenseGenerator { public final static String LEXICAL_UNIT = "lexicalUnit"; private final String resourceVersion; private final SynsetGenerator synsetGenerator; // SynsetGenerator private final SemanticClassLabelExtractor semanticClassLabelExtractor; // for extraction of semantic class labels private final Map<LexUnit, Sense> luSenseMappings = new HashMap<LexUnit, Sense>(); private final SenseExampleGenerator senseExampleGenerator; /** * Constructs a {@link SenseGenerator} for the consumed {@link GermaNet} instance * @param gnet GermaNet instance used for obtaining GermaNet's information * @resourceVersion Version of the resource */ public SenseGenerator(GermaNet gnet, String resourceVersion){ SynsetGenerator synsetGenerator = new SynsetGenerator(gnet, resourceVersion); synsetGenerator.initialize(); this.synsetGenerator= synsetGenerator; this.semanticClassLabelExtractor = new SemanticClassLabelExtractor(gnet); this.senseExampleGenerator = new SenseExampleGenerator(); this.resourceVersion = resourceVersion; } /** * This method consumes a group of LexUnits and creates list of {@link Sense}-instances * for every {@link LexUnit} of the consumed group * @param luGroup a group of LexUnits for which senses should be created * @return a {@link List} of senses generated from every LexUnit in luGroup */ public List<Sense> generateSenses(Set<LexUnit> luGroup){ List<Sense> senses = new ArrayList<Sense>(); // Generate Sense for each LexUnit in the group for(LexUnit lu : luGroup){ Sense sense = synsetGenerator.getSense(lu); luSenseMappings.put(lu, sense); // Creating Index sense.setIndex(lu.getSense()); // Create synset-reference de.tudarmstadt.ukp.lmf.model.semantics.Synset lmfSynset = synsetGenerator.getLMFSynset(lu); sense.setSynset(lmfSynset); // set semanticLabels List<SemanticLabel> semanticLabels = new LinkedList<SemanticLabel>(); SemanticLabel semanticLabel = new SemanticLabel(); semanticLabels.add(semanticLabel); semanticLabel.setLabel(semanticClassLabelExtractor.getLUSemanticClassLabel(lu)); semanticLabel.setType(ELabelTypeSemantics.semanticField); if(lu.isArtificial()){ // another semantic label for artificial LexUnits SemanticLabel semanticLabelArt = new SemanticLabel(); semanticLabelArt.setLabel("artificialConcept"); semanticLabelArt.setType(ELabelTypeSemantics.resourceSpecific); semanticLabels.add(semanticLabelArt); } sense.setSemanticLabels(semanticLabels); //*** Generating SenseExamples ***// List<SenseExample> senseExamples = senseExampleGenerator.generateSenseExamples(lu); sense.setSenseExamples(senseExamples); //*** Setting Definitions ***// //JEK synset glosses should not be duplicated // TODO check for uniform behavior of GermaNet, WordNet and the other resources with synsets //sense.setDefinitions(lmfSynset.getDefinitions()); List<WiktionaryParaphrase> paraphraseList = lu.getWiktionaryParaphrases(); List<Definition> definitions = new LinkedList<Definition>(); for (WiktionaryParaphrase paraphrase : paraphraseList) { String[] paraphraseString = paraphrase.toString().split("Wiktionary sense definition:"); String writtenText = paraphraseString[1].replaceAll(", edited:.*", ""); if (writtenText != null && !writtenText.equals("") && !writtenText.equals(" ")) { Definition definition = new Definition(); List<TextRepresentation> textRepresentations = new LinkedList<TextRepresentation>(); TextRepresentation textRepresentation = new TextRepresentation(); textRepresentation.setLanguageIdentifier(ELanguageIdentifier.GERMAN); textRepresentation.setWrittenText(writtenText); textRepresentations.add(textRepresentation); definition.setTextRepresentations(textRepresentations); definitions.add(definition); } } sense.setDefinitions(definitions); // *** Generating Monolingual ExternalRef**// MonolingualExternalRef mer = new MonolingualExternalRef(); mer.setExternalReference(Integer.toString(lu.getId())); mer.setExternalSystem(resourceVersion + "_" + LEXICAL_UNIT); LinkedList<MonolingualExternalRef> mers = new LinkedList<MonolingualExternalRef>(); mers.add(mer); sense.setMonolingualExternalRefs(mers); // Adding this sense to the group of generated sense for the consumed luGroup senses.add(sense); // Set the senseRelations setSenseRelations(lu); } return senses; } /** * This method consumes an instance of {@link LexUnit} and generates sense relations associated with the * consumed lexical relation * @param lu LexUnit for which corresponding instances of {@link SenseRelation} should be generated, * based on the consumed {@link LexRel} * @param lexRelation lexical relation for which the list of associated sense relations should be returned * @return a {@link List} of SenseRelations for the consumed lu and lexRelation */ private List<SenseRelation> generateSenseRelation(LexUnit lu, LexRel lexRelation){ List<SenseRelation> senseRelations = new LinkedList<SenseRelation>(); // Generating Relations List<LexUnit> targets = lu.getRelatedLexUnits(lexRelation); if(!targets.isEmpty()){ // If lu has a lexRelation to other lus, a sense Relation should be generated HashSet<SenseRelation> temp = new HashSet<SenseRelation>(); ERelTypeSemantics relType = getRelType(lexRelation); String relName = getRelName(lexRelation); for(LexUnit target : targets){ // Generate a SenseRelation SenseRelation senseRelation = new SenseRelation(); // Set targeted Sense senseRelation.setTarget(synsetGenerator.getSense(target)); // Setting relType and relName senseRelation.setRelType(relType); senseRelation.setRelName(relName); temp.add(senseRelation); } senseRelations.addAll(temp); } return senseRelations; } /** * This method consumes an instance of {@link LexUnit} and generates sense relations associated with the * consumed conceptual relation * @param lu LexUnit for which corresponding instances of {@link SenseRelation} should be generated, * based on the consumed {@link ConRel} * @param conRelation conceptual relation for which the list of associated sense relations should be returned * @return a {@link List} of SenseRelations for the consumed lu and conRelation */ private List<SenseRelation> generateSenseRelation(LexUnit lu, ConRel conRelation){ List<SenseRelation> senseRelations = new LinkedList<SenseRelation>(); // Generating Relation List<Synset> targets = lu.getSynset().getRelatedSynsets(conRelation); if(!targets.isEmpty()){ // If lu's Synset has a conRelation to other Synsets, a sense Relation should be generated HashSet<SenseRelation> temp = new HashSet<SenseRelation>(); ERelTypeSemantics relType = getRelType(conRelation); String relName = getRelName(conRelation); for(Synset target : targets){ // Generate a SenseRelation SenseRelation senseRelation = new SenseRelation(); senseRelation.setTarget(synsetGenerator.getSense(target)); senseRelation.setRelType(relType); senseRelation.setRelName(relName); temp.add(senseRelation); } senseRelations.addAll(temp); } return senseRelations; } /** * This method consumes a lexical relation and returns the * corresponding Uby-LMF relation type * @param lexRel for which Uby-LMF relation type should be returned * @return lexRel's relation type in Uby-LMF or null if no entry for lexRel exists * @see LexRel * @see ERelTypeSemantics */ private ERelTypeSemantics getRelType(LexRel lexRel){ ERelTypeSemantics relType = null; switch (lexRel){ case has_antonym : relType = ERelTypeSemantics.complementary; break; case has_synonym : relType = ERelTypeSemantics.association; break; default : System.err.println("Error, LexicalRelation not recognized: "+lexRel); System.exit(1); } return relType; } /** * This method consumes a lexical relation and returns the * corresponding Uby-LMF relation name * @param lexRel for which Uby-LMF relation name should be returned * @return lexRel's relation name in Uby-LMF or null if no entry for lexRel exists * @see LexRel * @see ERelTypeSemantics */ private String getRelName(LexRel lexRel){ String relName; switch (lexRel){ case has_antonym : relName = ERelNameSemantics.ANTONYM; break; case has_synonym : relName = ERelNameSemantics.SYNONYM; break; default : relName = null; } return relName; } /** * This method consumes a conceptual relation and returns the * corresponding Uby-LMF relation type * @param conRel for which Uby-LMF relation type should be returned * @return conRel relation type in Uby-LMF or null if no entry for conRel exists * @see ConRel * @see ERelTypeSemantics */ private ERelTypeSemantics getRelType(ConRel conRel){ ERelTypeSemantics relType; switch (conRel){ case causes : relType = ERelTypeSemantics.taxonomic; break; case entails : relType = ERelTypeSemantics.taxonomic; break; case has_component_holonym : relType = ERelTypeSemantics.partWhole; break; case has_component_meronym : relType = ERelTypeSemantics.partWhole; break; case has_hypernym : relType = ERelTypeSemantics.taxonomic ; break; case has_hyponym : relType = ERelTypeSemantics.taxonomic; break; case has_member_holonym : relType = ERelTypeSemantics.partWhole; break; case has_member_meronym : relType = ERelTypeSemantics.partWhole; break; case has_portion_holonym : relType = ERelTypeSemantics.partWhole; break; case has_portion_meronym : relType = ERelTypeSemantics.partWhole; break; case has_substance_holonym : relType = ERelTypeSemantics.partWhole; break; case has_substance_meronym : relType = ERelTypeSemantics.partWhole; break; case is_entailed_by : relType = ERelTypeSemantics.taxonomic; break; case is_related_to : relType = ERelTypeSemantics.association; break; default : relType = null; } return relType; } /** * This method consumes a conceptual relation and returns the * corresponding Uby-LMF relation name * @param conRel for which Uby-LMF relation name should be returned * @return conRel's relation name in Uby-LMF or null if no entry for conRel exists * @see ConRel * @see ERelTypeSemantics */ private String getRelName(ConRel conRel){ String relName; switch (conRel){ case causes : relName = ERelNameSemantics.CAUSES; break; case entails : relName = ERelNameSemantics.ENTAILS; break; case has_component_holonym : relName = ERelNameSemantics.HOLONYMCOMPONENT; break; case has_component_meronym : relName = ERelNameSemantics.MERONYMCOMPONENT; break; case has_hypernym : relName = ERelNameSemantics.HYPERNYM; break; case has_hyponym : relName = ERelNameSemantics.HYPONYM; break; case has_member_holonym : relName = ERelNameSemantics.HOLONYMMEMBER; break; case has_member_meronym : relName = ERelNameSemantics.MERONYMMEMBER; break; case has_portion_holonym : relName = ERelNameSemantics.HOLONYMPORTION; break; case has_portion_meronym : relName = ERelNameSemantics.MERONYMPORTION; break; case has_substance_holonym : relName = ERelNameSemantics.HOLONYMSUBSTANCE; break; case has_substance_meronym : relName = ERelNameSemantics.MERONYMSUBSTANCE; break; case is_entailed_by : relName = ERelNameSemantics.ENTAILEDBY; break; case is_related_to : relName = ERelNameSemantics.RELATED; break; default : relName = null; } return relName; } /** * This method consumes an instance of {@link LexUnit} and appends all sense relations to * sense associated with the consumed lexical unit. * @param lu to which sense, sense relation should be generated and appended * @see Sense * @see SenseRelation */ private void setSenseRelations(LexUnit lu){ List<SenseRelation> senseRelations = new ArrayList<SenseRelation>(); senseRelations.addAll(generateSenseRelation(lu, LexRel.has_antonym)); senseRelations.addAll(generateSenseRelation(lu, LexRel.has_synonym)); for(ConRel conRel : ConRel.values()) { senseRelations.addAll(generateSenseRelation(lu, conRel)); } Sense sense = synsetGenerator.getSense(lu); if(!senseRelations.isEmpty()) { sense.setSenseRelations(senseRelations); } } /** * Returns instance of {@link SynsetGenerator} associated with this {@link SenseGenerator} * @return the synset generator associated with this sense generator */ public SynsetGenerator getSynsetGenerator() { return synsetGenerator; } /** * This method consumes a lexical unit and returns the associated sense * @param lu which associated sense will be returned * @return sense that corresponds to the consumed lu, or null if this sense generator has not processed this lu yet * @see LexUnit * @see Sense * @see SenseGenerator */ public Sense getSense(LexUnit lu){ return luSenseMappings.get(lu); } }