/******************************************************************************* * Copyright 2012 University of Southern California * * 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. * * This code was developed by the Information Integration Group as part * of the Karma project at the Information Sciences Institute of the * University of Southern California. For more information, publications, * and related projects, please see: http://www.isi.edu/integration ******************************************************************************/ package edu.isi.karma.kr2rml.mapping; import edu.isi.karma.controller.history.CommandHistory; import edu.isi.karma.controller.history.HistoryJsonUtil; import edu.isi.karma.kr2rml.*; import edu.isi.karma.kr2rml.formatter.KR2RMLColumnNameFormatterFactory; import edu.isi.karma.kr2rml.planning.TriplesMap; import edu.isi.karma.kr2rml.planning.TriplesMapLink; import edu.isi.karma.kr2rml.template.*; import edu.isi.karma.modeling.alignment.Alignment; import edu.isi.karma.modeling.ontology.OntologyManager; import edu.isi.karma.rep.Worksheet; import edu.isi.karma.rep.Workspace; import edu.isi.karma.rep.alignment.*; import edu.isi.karma.rep.metadata.WorksheetProperties.Property; import edu.isi.karma.rep.metadata.WorksheetProperties.SourceTypes; import edu.isi.karma.transformation.tokenizer.PythonTransformationAsURITokenizer; import edu.isi.karma.transformation.tokenizer.PythonTransformationAsURIValidator; import edu.isi.karma.transformation.tokenizer.PythonTransformationToken; import edu.isi.karma.webserver.KarmaException; import org.jgrapht.graph.DirectedWeightedMultigraph; import org.json.JSONArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.isi.karma.config.ModelingConfiguration; import edu.isi.karma.config.ModelingConfigurationRegistry; import edu.isi.karma.webserver.ContextParametersRegistry; import edu.isi.karma.webserver.ServletContextParameterMap; import java.net.MalformedURLException; import java.net.URL; import java.util.*; import java.util.Map.Entry; public class KR2RMLMappingGenerator { private OntologyManager ontMgr; private String sourceNamespace; private KR2RMLMapping r2rmlMapping; private KR2RMLMappingColumnNameHNodeTranslator translator; private PythonTransformationToTemplateTermSetBuilder transformationToTemplateTermSet; private final Node steinerTreeRoot; private SemanticTypes semanticTypes; private DirectedWeightedMultigraph<Node, LabeledLink> alignmentGraph; private Worksheet worksheet; private Workspace workspace; // Internal data structures required private int synonymIdCounter; private static Logger logger = LoggerFactory.getLogger(KR2RMLMappingGenerator.class); public KR2RMLMappingGenerator(Workspace workspace, Worksheet worksheet, Alignment alignment, SemanticTypes semanticTypes, String sourcePrefix, String sourceNamespace, boolean generateInverse) throws KarmaException{ this(workspace, worksheet, alignment, semanticTypes, sourcePrefix, sourceNamespace, generateInverse, null, false); } public KR2RMLMappingGenerator(Workspace workspace, Worksheet worksheet, Alignment alignment, SemanticTypes semanticTypes, String sourcePrefix, String sourceNamespace, boolean generateInverse, JSONArray history, boolean onlyHistory) throws KarmaException{ this.workspace = workspace; this.worksheet = worksheet; this.translator = new KR2RMLMappingColumnNameHNodeTranslator(workspace.getFactory(), worksheet); this.transformationToTemplateTermSet = new PythonTransformationToTemplateTermSetBuilder(translator, workspace.getFactory()); this.ontMgr = workspace.getOntologyManager(); this.semanticTypes = semanticTypes; this.sourceNamespace = sourceNamespace; R2RMLMappingIdentifier id = null; try { id = new R2RMLMappingIdentifier(sourceNamespace, new URL(sourceNamespace+ sourcePrefix + UUID.randomUUID())); } catch (MalformedURLException e) { logger.error("Unable to create mapping identifier", e); } this.r2rmlMapping = new KR2RMLMapping(id, KR2RMLVersion.getCurrent()); this.alignmentGraph = alignment.getSteinerTree(); this.steinerTreeRoot = alignment.GetTreeRoot(); // Generate the R2RML data structures if (!onlyHistory) { generateMappingFromSteinerTree(generateInverse); } addWorksheetHistory(history); addSourceType(worksheet); if (!onlyHistory) { addColumnNameFormatter(); } determineIfMappingIsR2RMLCompatible(worksheet); } private void addSourceType(Worksheet worksheet) { String sourceType = worksheet.getMetadataContainer().getWorksheetProperties().getPropertyValue(Property.sourceType); r2rmlMapping.setSourceType(SourceTypes.valueOf(sourceType)); } private void determineIfMappingIsR2RMLCompatible(Worksheet worksheet2) { boolean isRMLCompatible = KR2RMLWorksheetHistoryCompatibilityVerifier.verify(workspace, r2rmlMapping.getWorksheetHistory()); r2rmlMapping.setRMLCompatible(isRMLCompatible); if(isRMLCompatible && r2rmlMapping.getSourceType().equals(SourceTypes.DB)) { r2rmlMapping.setR2RMLCompatible(true); } } private void addColumnNameFormatter() { r2rmlMapping.setColumnNameFormatter(KR2RMLColumnNameFormatterFactory.getFormatter(r2rmlMapping.getSourceType())); } private void addWorksheetHistory(JSONArray history) { if(history != null) { r2rmlMapping.setWorksheetHistory(history); } else { String filename = CommandHistory.getHistorySaver(workspace.getId()).getHistoryFilepath(worksheet.getId()); if(!HistoryJsonUtil.historyExists(workspace.getId(), worksheet.getId())) { logger.error("Worksheet history file not found! Can't write worksheet history " + "into R2RML model. Path:" + filename); return; } try { JSONArray historyArr = CommandHistory.getHistorySaver(workspace.getId()).loadHistory(filename); r2rmlMapping.setWorksheetHistory(historyArr); } catch(Exception e) { logger.error("Unable to read worksheet history from file: " + filename); } } } public Node getSteinerTreeRoot() { return steinerTreeRoot; } public KR2RMLMapping getKR2RMLMapping() { return this.r2rmlMapping; } private void generateMappingFromSteinerTree(boolean generateInverse) throws KarmaException { // Generate TriplesMap for each InternalNode in the tree createSubjectMaps(); // Create TripleMaps createTripleMaps(); // Identify the object property links createPredicateObjectMaps(generateInverse); // Identify blank nodes and generate backward links data structure for the triple maps identifyBlankNodes(); // Calculate the nodes covered by each InternalNode calculateColumnNodesCoveredByBlankNodes(); addPrefixes(); } private void addPrefixes() { Map<String, String> prefixMap = workspace.getOntologyManager().getPrefixMap(); for (Entry<String, String> entry :prefixMap.entrySet()) { Prefix p = new Prefix(entry.getValue(), entry.getKey()); r2rmlMapping.addPrefix(p); } } private void identifyBlankNodes() { for (SubjectMap subjMap:r2rmlMapping.getSubjectMapIndex().values()) { if (subjMap.getTemplate().getAllTerms().size() == 1 && (subjMap.getTemplate().getAllTerms().get(0) instanceof StringTemplateTerm)) { String str = subjMap.getTemplate().getAllTerms().get(0).getTemplateTermValue(); if (str.equals(sourceNamespace)) subjMap.setAsBlankNode(true); } } } private void calculateColumnNodesCoveredByBlankNodes() throws KarmaException { DisplayModel dm = new DisplayModel(alignmentGraph); for (Node treeNode:alignmentGraph.vertexSet()) { if (treeNode instanceof InternalNode && r2rmlMapping.getSubjectMapIndex().containsKey(treeNode.getId())) { SubjectMap subjMap = r2rmlMapping.getSubjectMapIndex().get(treeNode.getId()); if (subjMap.isBlankNode()) { List<String> columnsCovered = new ArrayList<>(); Set<LabeledLink> links = dm.getOutgoingEdgesOf(treeNode); Iterator<LabeledLink> linkIterator = links.iterator(); while(linkIterator.hasNext()) { Node n = linkIterator.next().getTarget(); if(n instanceof ColumnNode) { String columnName = translator.getColumnNameForHNodeId(((ColumnNode)n).getId()); columnsCovered.add(columnName); } } if(columnsCovered.isEmpty()) { //throw new KarmaException("You need to define a URI for "+treeNode.getDisplayId()+ "."); } r2rmlMapping.getAuxInfo().getBlankNodesColumnCoverage().put(treeNode.getId(), columnsCovered); r2rmlMapping.getAuxInfo().getBlankNodesUriPrefixMap().put(treeNode.getId(), treeNode.getDisplayId()); r2rmlMapping.getAuxInfo().getSubjectMapIdToTemplateAnchor().put(treeNode.getId(), KR2RMLMappingAuxillaryInformation.findSubjectMapTemplateAnchor(columnsCovered)); } } } } private void createTripleMaps() { Set<Node> nodes = alignmentGraph.vertexSet(); for (Node node:nodes) { if (node instanceof InternalNode) { // Create a TriplesMap corresponding to the Internal node SubjectMap subjMap = r2rmlMapping.getSubjectMapIndex().get(node.getId()); TriplesMap trMap = new TriplesMap(TriplesMap.getNewId(), subjMap); r2rmlMapping.getTriplesMapIndex().put(node.getId(), trMap); this.r2rmlMapping.addTriplesMap(trMap); r2rmlMapping.getAuxInfo().getTriplesMapGraph().addTriplesMap(trMap); } } } private void createSubjectMaps() { Set<Node> nodes = alignmentGraph.vertexSet(); for (Node node:nodes) { if (node instanceof InternalNode) { SubjectMap subj = new SubjectMap(node.getId()); if (node.getId().equals(steinerTreeRoot.getId())) subj.setAsSteinerTreeRootNode(true); // Add the user provided namespace as the first template term subj.getTemplate().addTemplateTermToSet(new StringTemplateTerm(sourceNamespace)); StringTemplateTerm typeTerm = new StringTemplateTerm(node.getLabel().getUri(), true); TemplateTermSet typeTermSet = new TemplateTermSet(); typeTermSet.addTemplateTermToSet(typeTerm); subj.addRdfsType(typeTermSet); ServletContextParameterMap contextParameters = ContextParametersRegistry.getInstance().getContextParameters(workspace.getContextId()); ModelingConfiguration modelingConfiguration = ModelingConfigurationRegistry.getInstance().register(contextParameters.getId()); if(modelingConfiguration.getR2rmlExportSuperClass()) { OntologyManager ontMgr = workspace.getOntologyManager(); HashMap<String,Label> superClassLabelsMap = ontMgr.getSuperClasses(node.getLabel().getUri(), true); for(String key: superClassLabelsMap.keySet()) { Label superClassLabel = superClassLabelsMap.get(key); StringTemplateTerm supertypeTerm = new StringTemplateTerm(superClassLabel.getUri(), false); TemplateTermSet supertypeTermSet = new TemplateTermSet(); supertypeTermSet.addTemplateTermToSet(supertypeTerm); subj.addRdfsType(supertypeTermSet); } } r2rmlMapping.getSubjectMapIndex().put(node.getId(), subj); Set<LabeledLink> outgoingLinks = alignmentGraph.outgoingEdgesOf(node); for (LabeledLink link:outgoingLinks) { if (link instanceof ClassInstanceLink || link instanceof ColumnSubClassLink) { Node tNode = link.getTarget(); if (tNode instanceof ColumnNode) { ColumnNode cnode = (ColumnNode) tNode; String hNodeId = cnode.getHNodeId(); String columnName = translator.getColumnNameForHNodeId(hNodeId); ColumnTemplateTerm cnTerm = new ColumnTemplateTerm(columnName); // Identify classInstance links to set the template if (link instanceof ClassInstanceLink) { TemplateTermSet tts = expandColumnTemplateTermForPyTransforms( hNodeId, cnTerm); subj.setTemplate(tts); } // Identify the isSubclassOfClass links to set the correct type else if (link instanceof ColumnSubClassLink) { TemplateTermSet typeTermSet2 = new TemplateTermSet(); typeTermSet2.addTemplateTermToSet(cnTerm); subj.addRdfsType(typeTermSet2); } List<String> columnsCovered = new LinkedList<>(); for(TemplateTerm term : subj.getTemplate().getAllColumnNameTermElements()) { columnsCovered.add(term.getTemplateTermValue()); } r2rmlMapping.getAuxInfo().getSubjectMapIdToTemplateAnchor().put(subj.getId(), KR2RMLMappingAuxillaryInformation.findSubjectMapTemplateAnchor(columnsCovered)); } else { logger.error("Target node of Class Instance link should always be a " + "column node."); } } } } else if(node instanceof LiteralNode) { LiteralNode literalNode = (LiteralNode)node; SubjectMap subj = new SubjectMap(literalNode.getId()); if (literalNode.getId().equals(steinerTreeRoot.getId())) subj.setAsSteinerTreeRootNode(true); StringTemplateTerm typeTerm = new StringTemplateTerm(literalNode.getLabel().getUri(), true); TemplateTermSet typeTermSet = new TemplateTermSet(); typeTermSet.addTemplateTermToSet(typeTerm); subj.addRdfsType(typeTermSet); TemplateTermSet templateTermSet = new TemplateTermSet(); StringTemplateTerm tempTerm = new StringTemplateTerm(literalNode.getValue(), literalNode.isUri()); templateTermSet.addTemplateTermToSet(tempTerm); subj.setTemplate(templateTermSet); r2rmlMapping.getSubjectMapIndex().put(node.getId(), subj); } } } private TemplateTermSet expandColumnTemplateTermForPyTransforms( String hNodeId, ColumnTemplateTerm cnTerm) { TemplateTermSet tts = null; String pythonCommand = worksheet.getMetadataContainer().getColumnMetadata().getColumnPython(hNodeId); List<PythonTransformationToken> tokens = PythonTransformationAsURITokenizer.tokenize(pythonCommand); PythonTransformationAsURIValidator validator = new PythonTransformationAsURIValidator(); if(validator.validate(tokens)) { tts = this.transformationToTemplateTermSet.translate(tokens, hNodeId); } else { tts = new TemplateTermSet(); tts.addTemplateTermToSet(cnTerm); } return tts; } private void createPredicateObjectMaps(boolean generateInverse) { Set<Node> nodes = alignmentGraph.vertexSet(); for (Node node:nodes) { if (node instanceof InternalNode) { // Create a TriplesMap corresponding to the Internal node SubjectMap subjMap = r2rmlMapping.getSubjectMapIndex().get(node.getId()); TriplesMap subjTrMap = r2rmlMapping.getTriplesMapIndex().get(node.getId()); // Create the predicate object map for each outgoing link Set<LabeledLink> outgoingEdges = alignmentGraph.outgoingEdgesOf(node); for (LabeledLink olink:outgoingEdges) { if (olink instanceof ObjectPropertySpecializationLink || olink instanceof DataPropertyOfColumnLink || olink instanceof ColumnSubClassLink) continue; PredicateObjectMap poMap = new PredicateObjectMap(PredicateObjectMap.getNewId(), subjTrMap); Node target = olink.getTarget(); // Create an object property map if (target instanceof InternalNode) { // Get the RefObjMap object for the objectmap TriplesMap objTrMap = r2rmlMapping.getTriplesMapIndex().get(target.getId()); RefObjectMap refObjMap = new RefObjectMap(RefObjectMap.getNewRefObjectMapId(), objTrMap); ObjectMap objMap = new ObjectMap(target.getId(), refObjMap); poMap.setObject(objMap); // Create the predicate Predicate pred = new Predicate(olink.getId()); // Check if a specialization link exists LabeledLink specializedEdge = getSpecializationLinkIfExists(olink, node); if (specializedEdge != null) { Node specializedEdgeTarget = specializedEdge.getTarget(); if (specializedEdgeTarget instanceof ColumnNode) { String columnName = translator.getColumnNameForHNodeId(((ColumnNode) specializedEdgeTarget).getHNodeId()); ColumnTemplateTerm cnTerm = new ColumnTemplateTerm(columnName); pred.getTemplate().addTemplateTermToSet(cnTerm); } } else { pred.getTemplate().addTemplateTermToSet( new StringTemplateTerm(olink.getLabel().getUri(), true)); } poMap.setPredicate(pred); if (generateInverse) addInversePropertyIfExists(subjMap, poMap, olink, subjTrMap); // Add the links in the graph links data structure TriplesMapLink link = new TriplesMapLink(subjTrMap, objTrMap, poMap); r2rmlMapping.getAuxInfo().getTriplesMapGraph().addLink(link); } else if(target instanceof LiteralNode) { LiteralNode lnode = (LiteralNode) target; //Create the object TemplateTermSet termSet = new TemplateTermSet(); StringTemplateTerm literalTerm = new StringTemplateTerm(lnode.getValue(), lnode.isUri()); termSet.addTemplateTermToSet(literalTerm); StringTemplateTerm rdfLiteralTypeTerm = new StringTemplateTerm(lnode.getLabel().getUri(), true); TemplateTermSet rdfLiteralTypeTermSet = new TemplateTermSet(); rdfLiteralTypeTermSet.addTemplateTermToSet(rdfLiteralTypeTerm); String language = lnode.getLanguage(); StringTemplateTerm languageTerm = new StringTemplateTerm(language, false); TemplateTermSet languageTermSet = new TemplateTermSet(); languageTermSet.addTemplateTermToSet(languageTerm); ObjectMap objMap = new ObjectMap(target.getId(), termSet, rdfLiteralTypeTermSet, languageTermSet); poMap.setObject(objMap); // Create the predicate Predicate pred = new Predicate(olink.getId()); pred.getTemplate().addTemplateTermToSet( new StringTemplateTerm(olink.getLabel().getUri(), true)); poMap.setPredicate(pred); if (generateInverse) addInversePropertyIfExists(subjMap, poMap, olink, subjTrMap); } // Create a data property map else if(target instanceof ColumnNode) { // Create the object map ColumnNode cnode = (ColumnNode) target; String hNodeId = cnode.getHNodeId(); String columnName = translator.getColumnNameForHNodeId(hNodeId); ColumnTemplateTerm cnTerm = new ColumnTemplateTerm(columnName); TemplateTermSet termSet = expandColumnTemplateTermForPyTransforms( hNodeId, cnTerm); String rdfLiteralUri = cnode.getRdfLiteralType() == null? "" : cnode.getRdfLiteralType().getUri(); StringTemplateTerm rdfLiteralTypeTerm = new StringTemplateTerm(rdfLiteralUri, true); TemplateTermSet rdfLiteralTypeTermSet = new TemplateTermSet(); rdfLiteralTypeTermSet.addTemplateTermToSet(rdfLiteralTypeTerm); String language = cnode.getLanguage(); StringTemplateTerm languageTerm = new StringTemplateTerm(language, false); TemplateTermSet languageTermSet = new TemplateTermSet(); languageTermSet.addTemplateTermToSet(languageTerm); ObjectMap objMap = new ObjectMap(hNodeId, termSet, rdfLiteralTypeTermSet, languageTermSet); poMap.setObject(objMap); // Create the predicate Predicate pred = new Predicate(olink.getId()); // Check if a specialization link exists LabeledLink specializedEdge = getSpecializationLinkIfExists(olink, node); if (specializedEdge != null) { Node specializedEdgeTarget = specializedEdge.getTarget(); if (specializedEdgeTarget instanceof ColumnNode) { String targetColumnName = translator.getColumnNameForHNodeId(((ColumnNode) specializedEdgeTarget).getHNodeId()); ColumnTemplateTerm cnsplTerm = new ColumnTemplateTerm(targetColumnName); pred.getTemplate().addTemplateTermToSet(cnsplTerm); } } else { pred.getTemplate().addTemplateTermToSet( new StringTemplateTerm(olink.getLabel().getUri(), true)); } poMap.setPredicate(pred); // Save link from the columnName to the its PredicateObjectMap in the auxiliary information saveLinkFromColumnNameToPredicateObjectMap(columnName, poMap); // Check for synonym types for this column addSynonymTypesPredicateObjectMaps(subjTrMap, hNodeId); } // Add the predicateobjectmap to the triples map after a sanity check if (poMap.getObject() != null && poMap.getPredicate() != null && !doesPredicateAlreadyExist(subjTrMap, poMap, poMap.getObject().getRefObjectMap())) subjTrMap.addPredicateObjectMap(poMap); } } } } private void saveLinkFromColumnNameToPredicateObjectMap(String columnName, PredicateObjectMap poMap) { List<PredicateObjectMap> pomList = r2rmlMapping.getAuxInfo().getColumnNameToPredObjLinks().get(columnName); if (pomList == null) { pomList = new ArrayList<>(); } pomList.add(poMap); r2rmlMapping.getAuxInfo().getColumnNameToPredObjLinks().put(columnName, pomList); } private void addSynonymTypesPredicateObjectMaps(TriplesMap subjTrMap, String hNodeId) { SynonymSemanticTypes synonyms = this.semanticTypes.getSynonymTypesForHNodeId(hNodeId); if (synonyms != null && !synonyms.getSynonyms().isEmpty()){ for (SemanticType synType:synonyms.getSynonyms()) { if (synType.isClass()) { logger.error("Synonym type as class with no property are not allowed."); continue; } PredicateObjectMap poMap = new PredicateObjectMap(PredicateObjectMap.getNewId(),subjTrMap); // Create the object map String columnName = translator.getColumnNameForHNodeId(hNodeId); ColumnTemplateTerm cnTerm = new ColumnTemplateTerm(columnName); TemplateTermSet termSet = new TemplateTermSet(); termSet.addTemplateTermToSet(cnTerm); ObjectMap objMap = new ObjectMap(hNodeId, termSet, null); poMap.setObject(objMap); // Create the predicate Predicate pred = new Predicate(synType.getType().getUri() + "-synonym" + getNewSynonymIdCount()); pred.getTemplate().addTemplateTermToSet( new StringTemplateTerm(synType.getType().getUri(), true)); poMap.setPredicate(pred); // Add the predicate object map to the triples map subjTrMap.addPredicateObjectMap(poMap); // Save the link from hNodeId to PredicateObjectMap saveLinkFromColumnNameToPredicateObjectMap(columnName, poMap); } } } private int getNewSynonymIdCount() { return synonymIdCounter++; } private void addInversePropertyIfExists(SubjectMap subjMap, PredicateObjectMap poMap, LabeledLink olink, TriplesMap subjTrMap) { String propUri = olink.getLabel().getUri(); //this can happen if propertyName is not an Object property; it could be a subclass if (!ontMgr.isObjectProperty(propUri)) return; Label inversePropLabel = ontMgr.getInverseProperty(propUri); Label inverseOfPropLabel = ontMgr.getInverseOfProperty(propUri); if (inversePropLabel != null) { TriplesMap inverseTrMap = r2rmlMapping.getTriplesMapIndex().get(poMap.getObject().getId()); // Create the predicate object map PredicateObjectMap invPoMap = new PredicateObjectMap(PredicateObjectMap.getNewId(),inverseTrMap); // Create the predicate Predicate pred = new Predicate(olink.getId()+"+inverse"); pred.getTemplate().addTemplateTermToSet( new StringTemplateTerm(inversePropLabel.getUri(), true)); invPoMap.setPredicate(pred); // Create the object using RefObjMap RefObjectMap refObjMap = new RefObjectMap(RefObjectMap.getNewRefObjectMapId(), subjTrMap); ObjectMap invObjMap = new ObjectMap(subjMap.getId(), refObjMap); invPoMap.setObject(invObjMap); boolean alreadyExists = doesPredicateAlreadyExist(inverseTrMap, invPoMap, refObjMap); if(alreadyExists) { return; } inverseTrMap.addPredicateObjectMap(invPoMap); // Add the link to the link set r2rmlMapping.getAuxInfo().getTriplesMapGraph().addLink(new TriplesMapLink(inverseTrMap, subjTrMap, invPoMap)); } if (inverseOfPropLabel != null) { // Create the triples map // Get the object's triples map TriplesMap inverseOfTrMap = r2rmlMapping.getTriplesMapIndex().get(poMap.getObject().getId()); PredicateObjectMap invOfPoMap = new PredicateObjectMap(PredicateObjectMap.getNewId(),inverseOfTrMap); // Create the predicate Predicate pred = new Predicate(olink.getId()+"+inverseOf"); pred.getTemplate().addTemplateTermToSet( new StringTemplateTerm(inverseOfPropLabel.getUri(), true)); invOfPoMap.setPredicate(pred); // Create the object using RefObjMap RefObjectMap refObjMap = new RefObjectMap(RefObjectMap.getNewRefObjectMapId(), subjTrMap); ObjectMap invOfObjMap = new ObjectMap(subjMap.getId(), refObjMap); invOfPoMap.setObject(invOfObjMap); boolean alreadyExists = doesPredicateAlreadyExist(inverseOfTrMap, invOfPoMap, refObjMap); if(alreadyExists) { return; } inverseOfTrMap.addPredicateObjectMap(invOfPoMap); // Add the link to the link set r2rmlMapping.getAuxInfo().getTriplesMapGraph().addLink(new TriplesMapLink(inverseOfTrMap, subjTrMap, invOfPoMap)); } } private boolean doesPredicateAlreadyExist(TriplesMap triplesMap, PredicateObjectMap poMap, RefObjectMap refObjMap) { boolean alreadyExists = false; for(PredicateObjectMap pom : triplesMap.getPredicateObjectMaps()) { if(pom.getPredicate().getTemplate().isSingleUriString() && poMap.getPredicate().getTemplate().isSingleUriString()) { if(pom.getPredicate().getTemplate().toString().equalsIgnoreCase(poMap.getPredicate().getTemplate().toString())) { if(pom.getObject().hasRefObjectMap() && pom.getObject().getRefObjectMap().getParentTriplesMap().getId().equalsIgnoreCase(refObjMap.getParentTriplesMap().getId())) { alreadyExists = true; } else if(!pom.getObject().hasRefObjectMap() && !poMap.getObject().hasRefObjectMap() && pom.getObject().getTemplate().toString().compareTo(poMap.getObject().getTemplate().toString())== 0) { alreadyExists = true; } } } } return alreadyExists; } private LabeledLink getSpecializationLinkIfExists(LabeledLink link, Node sourceNode) { Set<LabeledLink> outgoingEdges = this.alignmentGraph.outgoingEdgesOf(sourceNode); for (LabeledLink olink:outgoingEdges) { // Check for the object property specialization if (olink instanceof ObjectPropertySpecializationLink ) { String splLinkId = ((ObjectPropertySpecializationLink) olink).getSpecializedLinkId(); if (splLinkId.equals(link.getId())) return olink; } // Check for the data property specialization else if (olink instanceof DataPropertyOfColumnLink) { DataPropertyOfColumnLink dlink = (DataPropertyOfColumnLink) olink; Node target = link.getTarget(); if (target instanceof ColumnNode) { ColumnNode cnode = (ColumnNode) target; if (dlink.getSpecializedColumnHNodeId().equals(cnode.getId())) return dlink; } } } return null; } }