/******************************************************************************* * Copyright 2016 * Ubiquitous Knowledge Processing (UKP) Lab * Technische Universität Darmstadt * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package de.tudarmstadt.ukp.lmf.transform.omegawiki; import java.io.UnsupportedEncodingException; import java.sql.SQLException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import de.tudarmstadt.ukp.lmf.model.core.Sense; import de.tudarmstadt.ukp.lmf.model.enums.ELabelTypeSemantics; 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.Synset; import de.tudarmstadt.ukp.lmf.model.semantics.SynsetRelation; import de.tudarmstadt.ukp.omegawiki.api.DefinedMeaning; import de.tudarmstadt.ukp.omegawiki.api.OWLanguage; import de.tudarmstadt.ukp.omegawiki.api.OmegaWiki; import de.tudarmstadt.ukp.omegawiki.api.SynTrans; import de.tudarmstadt.ukp.omegawiki.db.DatabaseStatements; import de.tudarmstadt.ukp.omegawiki.exception.OmegaWikiException; /** * This class is used for generating of SynsetRelations * @author matuschek * */ public class SynsetRelationGenerator { private final int GlobalLanguage; private final SynsetGenerator synsetGenerator; // SynsetGenerator is needed for extraction of Synset-Information private final LexicalEntryGenerator lexicalEntryGenerator; private final OmegaWiki ow ; /* * Mappings between relation names and and corresponding internal RelNames * Used for SynsetRelations only */ private HashMap<String, String> relNameMappings; /* * Mappings between relations and corresponding ERelTypes * Used for SynsetRelations only */ private HashMap<String, ERelTypeSemantics> relTypeMappings; private final Map<String, ELabelTypeSemantics> domainOfRegisterMappings = new HashMap<String,ELabelTypeSemantics>(); // <domainOfRelationKey, register> /** * Constructs a SynsetRelationGenerator * @param synsetGenerator SynsetGenerator is used for extraction of Synset-Informations, SynsetGenerator must be initialized! * @param lexicalEntryGenerator is used for extraction of LE-Information */ public SynsetRelationGenerator(SynsetGenerator synsetGenerator, LexicalEntryGenerator leg){ this.lexicalEntryGenerator=leg; this.synsetGenerator = synsetGenerator; this.GlobalLanguage=synsetGenerator.getGlobalLanguage(); ow = this.synsetGenerator.getOmegaWiki(); if(relNameMappings == null) { initializeMappings(); } } /** * This method iterates over all Synsets (provided by SynsetGenerator) * and updates their SynsetRelations * @throws UnsupportedEncodingException * @throws OmegaWikiException */ public void updateSynsetRelations() throws OmegaWikiException, UnsupportedEncodingException{ // Iterate over all Synset-Bindings and update int overall = synsetGenerator.getOWSynsetLMFSynsetMappings().size(); int current = 0; for(Entry<DefinedMeaning, Synset> binding : synsetGenerator.getOWSynsetLMFSynsetMappings().entrySet()) { updateSynsetRelations(binding); if(current++ % 1000 == 0) { System.out.println("Generating SynsetRelations... Finished " + ((current * 100) / overall) + "%"); } } } /** * This method consumes a Synset-Binding and updates the corresponding SynsetRelations * @param binding * @throws UnsupportedEncodingException * @throws OmegaWikiException */ private void updateSynsetRelations( Entry<DefinedMeaning, Synset> binding) throws OmegaWikiException, UnsupportedEncodingException { // Create SynsetRelation for this Binding List<SynsetRelation> synsetRelations = new LinkedList<SynsetRelation>(); DefinedMeaning dm = binding.getKey( ); Map<DefinedMeaning,Integer> targets = dm.getDefinedMeaningLinksAllLang(GlobalLanguage); //Handle invalid relations DefinedMeaning dummy; if ((dummy = dm.getSubject()) != null) { targets.put(dummy, -1); } // Iterate over all pointers of the DM and generate the corresponding SynsetRelation for(DefinedMeaning dmt : targets.keySet()) { SynsetRelation ssr = generateSynsetRelation(dm,dmt, targets.get(dmt)); if(ssr!=null) { synsetRelations.add(ssr); } } binding.getValue().setSynsetRelations(synsetRelations); } private DatabaseStatements dbStatements; /** * This method consumes two DMs plus relationtype as int and generates the corresponding SynsetRelation for it * * @param DefinedMeaning source * @param DefinedMeaning target * @param int type * @return generated SynsetRelation * @throws UnsupportedEncodingException * @throws OmegaWikiException */ private SynsetRelation generateSynsetRelation(DefinedMeaning source, DefinedMeaning target, int type) throws OmegaWikiException, UnsupportedEncodingException { // Create a SynsetRelation for these DMs SynsetRelation synsetRelation = new SynsetRelation(); DefinedMeaning rel = null; String relationName=""; if(type >0) { // rel = ow.getDefinedMeaningById(type); //TODO: Dirty hack! Return to old code as soon as https://code.google.com/p/jowkl/issues/detail?id=2 is fixed and released. if (dbStatements == null) { try { dbStatements = new DatabaseStatements(ow.getDatabaseConfiguration()); } catch (SQLException e) { throw new RuntimeException(e); } } rel = new DefinedMeaning(type, dbStatements); Set<SynTrans> sta = rel.getSynTranses(OWLanguage.English); if (!sta.isEmpty()) { relationName = sta.iterator().next().getSyntrans().getSpelling(); } } else { relationName="subject"; // Setting relationType } ERelTypeSemantics relType = getRelType(relationName); synsetRelation.setRelType(relType); // Setting relationName synsetRelation.setRelName(getRelationName(relationName)); // Setting the target // the target is a Synset. If it's not in the resource, skip it if(synsetGenerator.getLMFSynset(target)!=null) { synsetRelation.setTarget(synsetGenerator.getLMFSynset(target)); } else { return null; } /* * Updating SubjectField class * this block will only be executed for domain relations */ if(domainOfRegisterMappings.keySet().contains(getRelationName(relationName))){ // SenseGenerator is needed in order to obtain the Lexeme's corresponding Sense SenseGenerator senseGenerator = lexicalEntryGenerator.getSenseGenerator(); // Iterate over every lexeme of the source synset for(SynTrans lexeme : source.getSynTranses(GlobalLanguage)){ // Obtain lexeme's Sense Sense sense = senseGenerator.getSense(lexeme); List<SemanticLabel> semanticLabels = null; if(sense != null) { // obtain semantic labels semanticLabels = sense.getSemanticLabels(); } if(semanticLabels == null) { semanticLabels = new LinkedList<SemanticLabel>(); // Create a new SemanticLabel and add it to the list SemanticLabel semanticLabel = createSemanticLabel(target, getRelationName(relationName)); semanticLabels.add(semanticLabel); // set the subjectField sense.setSemanticLabels(semanticLabels); } } } return synsetRelation; } /** * This method consumes target DM of a Domain relation and generates the * corresponding instance of SemanticLabel class * @param targetDM * @param key describes the relation * @return instance of SemanticLabel class * @throws OmegaWikiException * @throws UnsupportedEncodingException */ private SemanticLabel createSemanticLabel(DefinedMeaning targetDM, String key) throws UnsupportedEncodingException, OmegaWikiException { SemanticLabel semanticLabel = new SemanticLabel(); semanticLabel.setLabel(getSemanticLabel(targetDM)); semanticLabel.setType(domainOfRegisterMappings.get(key)); return semanticLabel; } /** * This method consumes a DM * and returns the the lemma of the targetSynset's first lexeme * @param targetDM * @return the the lemma of the targetSynset's first lexeme * @throws OmegaWikiException * @throws UnsupportedEncodingException */ private String getSemanticLabel(DefinedMeaning targetDM) throws UnsupportedEncodingException, OmegaWikiException { Set<SynTrans> st = targetDM.getSynTranses(GlobalLanguage); if (!st.isEmpty()) { return st.iterator().next().getSyntrans().getSpelling(); } return ""; } /** * This method consumes a OW relation type and returns the corresponding Synset-relType * @param relation the relation in OW * @return corresponding RelType */ private ERelTypeSemantics getRelType(String relation) { ERelTypeSemantics ret = null; if ((ret = relTypeMappings.get(relation))!=null) { return ret; } else { return ERelTypeSemantics.predicative; } } /** * This method consumes a DM relation name and returns the corresponding Synset-relationName * @param relation the relation name * @return corresponding relationName */ private String getRelationName(String relation) { String ret = null; if ((ret = relNameMappings.get(relation))!=null) { return ret; } else { return relation; } } /** * This method initializes the relation mappings */ private void initializeMappings() { relNameMappings = new HashMap<String, String>(); relTypeMappings = new HashMap<String, ERelTypeSemantics>(); // Adding mappings // hypernym relNameMappings.put("hypernym", ERelNameSemantics.HYPERNYM); relTypeMappings.put("hypernym", ERelTypeSemantics.taxonomic); relNameMappings.put("has_hypernym", ERelNameSemantics.HYPERNYM); relTypeMappings.put("has_hypernym", ERelTypeSemantics.taxonomic); relNameMappings.put("hypernymInstance", ERelNameSemantics.HYPERNYM); relTypeMappings.put("hypernymInstance", ERelTypeSemantics.taxonomic); relNameMappings.put("broader term", ERelNameSemantics.HYPERNYM); relTypeMappings.put("broader term", ERelTypeSemantics.taxonomic); relNameMappings.put("parent", ERelNameSemantics.HYPERNYM); relTypeMappings.put("parent", ERelTypeSemantics.taxonomic); // hyponym relNameMappings.put("hyponym", ERelNameSemantics.HYPONYM); relTypeMappings.put("hyponym", ERelTypeSemantics.taxonomic); relNameMappings.put("has_hyponym", ERelNameSemantics.HYPONYM); relTypeMappings.put("has_hyponym", ERelTypeSemantics.taxonomic); relNameMappings.put("hyponymInstance", ERelNameSemantics.HYPONYM); relTypeMappings.put("hyponymInstance", ERelTypeSemantics.taxonomic); relNameMappings.put("narrower term", ERelNameSemantics.HYPONYM); relTypeMappings.put("narrower term", ERelTypeSemantics.taxonomic); relNameMappings.put("child", ERelNameSemantics.HYPONYM); relTypeMappings.put("child", ERelTypeSemantics.taxonomic); // holonymMember relNameMappings.put("holonym", ERelNameSemantics.HOLONYM); relTypeMappings.put("holonym",ERelTypeSemantics.partWhole); // meronymMember relNameMappings.put("meronym", ERelNameSemantics.MERONYM); relTypeMappings.put("meronym", ERelTypeSemantics.partWhole); // topic relNameMappings.put("is part of theme",ERelNameSemantics.RELATED); relTypeMappings.put("is part of theme", ERelTypeSemantics.association); // topic relNameMappings.put("subject",ERelNameSemantics.RELATED); relTypeMappings.put("subject", ERelTypeSemantics.association); // seeAlso relNameMappings.put("related term", ERelNameSemantics.RELATED); relTypeMappings.put("related term", ERelTypeSemantics.association); relNameMappings.put("is_related_to", ERelNameSemantics.RELATED); relTypeMappings.put("is_related_to", ERelTypeSemantics.association); // seeAlso // seeAlso relNameMappings.put("seeAlso", ERelNameSemantics.SEEALSO); relTypeMappings.put("seeAlso", ERelTypeSemantics.association); relNameMappings.put("holonymMember", ERelNameSemantics.HOLONYMMEMBER); relTypeMappings.put("holonymMember", ERelTypeSemantics.partWhole); relNameMappings.put("holonymPart", ERelNameSemantics.HOLONYMPART); relTypeMappings.put("holonymPart", ERelTypeSemantics.partWhole); relNameMappings.put("has_component_holonym", ERelNameSemantics.HOLONYMCOMPONENT); relTypeMappings.put("has_component_holonym", ERelTypeSemantics.partWhole); relNameMappings.put("has_substance_holonym", ERelNameSemantics.HOLONYMSUBSTANCE); relTypeMappings.put("has_substance_holonym", ERelTypeSemantics.partWhole); relNameMappings.put("has_member_holonym", ERelNameSemantics.MERONYMMEMBER); relTypeMappings.put("has_member_holonym", ERelTypeSemantics.partWhole); relNameMappings.put("meronymMember", ERelNameSemantics.MERONYMMEMBER); relTypeMappings.put("meronymMember", ERelTypeSemantics.partWhole); relNameMappings.put("meronymPart", ERelNameSemantics.MERONYMPART); relTypeMappings.put("meronymPart", ERelTypeSemantics.partWhole); relNameMappings.put("has_component_meronym", ERelNameSemantics.MERONYMCOMPONENT); relTypeMappings.put("has_component_meronym", ERelTypeSemantics.partWhole); relNameMappings.put("has_substance_meronym", ERelNameSemantics.MERONYMSUBSTANCE); relTypeMappings.put("has_substance_meronym", ERelTypeSemantics.partWhole); relNameMappings.put("has_member_meronym", ERelNameSemantics.MERONYMMEMBER); relTypeMappings.put("has_member_meronym", ERelTypeSemantics.partWhole); relNameMappings.put("entails", ERelNameSemantics.ENTAILS); relTypeMappings.put("entails", ERelTypeSemantics.predicative); relNameMappings.put("is_entailed_by", ERelNameSemantics.ENTAILEDBY); relTypeMappings.put("is_entailed_by", ERelTypeSemantics.predicative); relNameMappings.put("causes", ERelNameSemantics.CAUSES); relTypeMappings.put("causes", ERelTypeSemantics.predicative); relNameMappings.put("seeAlso", ERelNameSemantics.SEEALSO); relTypeMappings.put("seeAlso", ERelTypeSemantics.association); relNameMappings.put("antonym", ERelNameSemantics.ANTONYM); relTypeMappings.put("antonym", ERelTypeSemantics.complementary); // Setting mappings related to domainOf Relations domainOfRegisterMappings.put("is part of theme", ELabelTypeSemantics.domain); domainOfRegisterMappings.put("subject", ELabelTypeSemantics.domain); domainOfRegisterMappings.put("topic", ELabelTypeSemantics.domain); } }