/******************************************************************************* * Copyright 2014 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.planning; 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 java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.isi.karma.kr2rml.template.PopulatedTemplateTermSet; import edu.isi.karma.kr2rml.writer.KR2RMLRDFWriter; import edu.isi.karma.rep.Row; public class TriplesMapPlanGenerator { private static Logger LOG = LoggerFactory.getLogger(TriplesMapPlanGenerator.class); private Map<TriplesMap, TriplesMapWorkerPlan> triplesMapToWorkerPlan; private Set<String> unprocessedTriplesMapsIds = new HashSet<>(); private Row r; private List<KR2RMLRDFWriter> outWriters; public TriplesMapPlanGenerator(Map<TriplesMap, TriplesMapWorkerPlan> triplesMapToWorkerPlan, Row r, List<KR2RMLRDFWriter> outWriters) { this.triplesMapToWorkerPlan = triplesMapToWorkerPlan; this.r = r; this.outWriters = outWriters; } public TriplesMapPlan generatePlan(TriplesMapGraphMerger tmf, RootStrategy strategy) { List<TriplesMapWorker> workers = new LinkedList<>(); Map<String, List<PopulatedTemplateTermSet>>triplesMapSubjects = new ConcurrentHashMap<>(); TriplesMapPlan plan = new TriplesMapPlan(workers, r, triplesMapSubjects); List<TriplesMapGraph> graphs = tmf.getGraphs(); for(TriplesMapGraph graph : graphs) { //This can end up in deadlock. workers.addAll(generatePlan(graph, plan, strategy).values()); } return plan; } public TriplesMapPlan generatePlan(TriplesMapGraph graph, List<String> triplesMapProcessingOrder, RootStrategy strategy) { List<TriplesMapWorker> workers = new LinkedList<>(); Map<String, List<PopulatedTemplateTermSet>>triplesMapSubjects = new ConcurrentHashMap<>(); TriplesMapPlan plan = new TriplesMapPlan(workers, r, triplesMapSubjects); Map<TriplesMap, TriplesMapWorker> mapToWorker = generatePlan(graph, plan, strategy); for(String triplesMapId : triplesMapProcessingOrder) { TriplesMap map = graph.getTriplesMap(triplesMapId); if(!triplesMapToWorkerPlan.containsKey(map)) { LOG.error("No worker plan for " + triplesMapId); continue; } TriplesMapWorker worker = mapToWorker.get(map); if(worker != null) { workers.add(worker); } else { LOG.error("Graph is disconnected from " + triplesMapId ); } } return plan; } private Map<TriplesMap, TriplesMapWorker> generatePlan(TriplesMapGraph graph, TriplesMapPlan plan, RootStrategy strategy) { unprocessedTriplesMapsIds.addAll(graph.getTriplesMapIds()); //add strategy Map<TriplesMap, TriplesMapWorker> mapToWorker = new HashMap<>(); if(strategy == null) { strategy = new SteinerTreeRootStrategy(new WorksheetDepthRootStrategy()); } String triplesMapId = graph.findRoot(strategy); do { if(triplesMapId == null) { triplesMapId = unprocessedTriplesMapsIds.iterator().next(); } TriplesMap map = graph.getTriplesMap(triplesMapId); generateTriplesMapWorker(mapToWorker, graph, map, plan); triplesMapId = null; } while(!unprocessedTriplesMapsIds.isEmpty()); return mapToWorker; } private void generateTriplesMapWorker( Map<TriplesMap, TriplesMapWorker> mapToWorker, TriplesMapGraph graph, TriplesMap map, TriplesMapPlan plan) { if(!unprocessedTriplesMapsIds.remove(map.getId())) { LOG.error("already visited " + map.toString()); return; } if(!triplesMapToWorkerPlan.containsKey(map)) { LOG.error("No worker plan for " + map.getId()); return; } List<TriplesMapLink> links = graph.getAllNeighboringTriplesMap(map.getId()); List<TriplesMapWorker> workersDependentOn = new LinkedList<>(); for(TriplesMapLink link : links) { if((link.getSourceMap() == map && !link.isFlipped()) || (link.getTargetMap() == map && link.isFlipped())) { TriplesMap mapDependedOn = link.getSourceMap()==map? link.getTargetMap() : link.getSourceMap(); if(!mapToWorker.containsKey(mapDependedOn)) { generateTriplesMapWorker(mapToWorker, graph, mapDependedOn, plan); } if(triplesMapToWorkerPlan.containsKey(mapDependedOn)) { workersDependentOn.add(mapToWorker.get(mapDependedOn)); } else { LOG.error("Attempted to add dependency for "+map.getId() +" invalid triplesmap " + mapDependedOn.getId()); } } } TriplesMapWorker newWorker = new TriplesMapWorker(map, workersDependentOn, r, triplesMapToWorkerPlan.get(map), outWriters); mapToWorker.put(map, newWorker); for(TriplesMapWorker worker : workersDependentOn) { worker.addDependentTriplesMapWorker(newWorker); } } }