/******************************************************************************* * 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.controller.command.alignment; import java.io.PrintWriter; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.ws.rs.core.UriBuilder; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.isi.karma.config.ModelingConfiguration; import edu.isi.karma.config.ModelingConfigurationRegistry; import edu.isi.karma.controller.command.Command; import edu.isi.karma.controller.command.CommandException; import edu.isi.karma.controller.command.CommandType; import edu.isi.karma.controller.command.WorksheetCommand; import edu.isi.karma.controller.command.WorksheetSelectionCommand; import edu.isi.karma.controller.command.selection.SuperSelection; import edu.isi.karma.controller.history.CommandHistory; import edu.isi.karma.controller.history.CommandHistoryUtil; import edu.isi.karma.controller.history.HistoryJsonUtil; import edu.isi.karma.controller.update.AbstractUpdate; import edu.isi.karma.controller.update.ErrorUpdate; import edu.isi.karma.controller.update.HistoryUpdate; import edu.isi.karma.controller.update.TrivialErrorUpdate; import edu.isi.karma.controller.update.UpdateContainer; import edu.isi.karma.controller.update.WorksheetUpdateFactory; import edu.isi.karma.modeling.alignment.Alignment; import edu.isi.karma.modeling.alignment.AlignmentManager; import edu.isi.karma.modeling.alignment.SemanticModel; import edu.isi.karma.modeling.alignment.learner.ModelLearningGraph; import edu.isi.karma.modeling.alignment.learner.ModelLearningGraphType; import edu.isi.karma.modeling.alignment.learner.PatternWeightSystem; import edu.isi.karma.rep.HNode; import edu.isi.karma.rep.Worksheet; import edu.isi.karma.rep.Workspace; import edu.isi.karma.rep.alignment.InternalNode; import edu.isi.karma.rep.alignment.LabeledLink; import edu.isi.karma.rep.alignment.LinkStatus; import edu.isi.karma.rep.alignment.LinkType; import edu.isi.karma.rep.alignment.Node; import edu.isi.karma.rep.metadata.WorksheetProperties; import edu.isi.karma.rep.metadata.WorksheetProperties.Property; import edu.isi.karma.view.VWorkspace; import edu.isi.karma.webserver.ContextParametersRegistry; import edu.isi.karma.webserver.ServletContextParameterMap; import edu.isi.karma.webserver.ServletContextParameterMap.ContextParameter; import edu.isi.karma.webserver.WorkspaceKarmaHomeRegistry; public class GenerateR2RMLModelCommand extends WorksheetSelectionCommand { private String worksheetName; private String tripleStoreUrl; private String RESTserverAddress; private static Logger logger = LoggerFactory.getLogger(GenerateR2RMLModelCommand.class); public enum JsonKeys { updateType, fileUrl, worksheetId } public enum PreferencesKeys { rdfPrefix, rdfNamespace, modelSparqlEndPoint } protected GenerateR2RMLModelCommand(String id, String model, String worksheetId, String url, String selectionId) { super(id, model, worksheetId, selectionId); this.tripleStoreUrl = url; } public String getTripleStoreUrl() { return tripleStoreUrl; } public void setTripleStoreUrl(String tripleStoreUrl) { this.tripleStoreUrl = tripleStoreUrl; } public void setRESTserverAddress(String RESTserverAddress) { this.RESTserverAddress = RESTserverAddress; } @Override public String getCommandName() { return this.getClass().getSimpleName(); } @Override public String getTitle() { return "Generate R2RML Model"; } @Override public String getDescription() { return this.worksheetName; } @Override public CommandType getCommandType() { return CommandType.notInHistory; } @Override public UpdateContainer doIt(Workspace workspace) throws CommandException { final ServletContextParameterMap contextParameters = ContextParametersRegistry.getInstance().getContextParameters(workspace.getContextId()); ModelingConfiguration modelingConfiguration = ModelingConfigurationRegistry.getInstance().getModelingConfiguration(WorkspaceKarmaHomeRegistry.getInstance().getKarmaHome(workspace.getId())); String worksheetId = this.worksheetId; UpdateContainer uc = new UpdateContainer(); //save the preferences savePreferences(workspace); boolean storeOldHistory = modelingConfiguration.isStoreOldHistoryEnabled(); Worksheet worksheet = workspace.getWorksheet(worksheetId); SuperSelection selection = getSuperSelection(worksheet); CommandHistory history = workspace.getCommandHistory(); List<Command> oldCommands = history.getCommandsFromWorksheetId(worksheetId); if (storeOldHistory) { JSONArray oldCommandsArray = new JSONArray(); for (Command refined : oldCommands) oldCommandsArray.put(workspace.getCommandHistory().getCommandJSON(workspace, refined)); worksheet.getMetadataContainer().getWorksheetProperties().setPropertyValue( Property.oldCommandHistory, oldCommandsArray.toString()); } CommandHistoryUtil historyUtil = new CommandHistoryUtil(history.getCommandsFromWorksheetId(worksheetId), workspace, worksheetId); boolean isHistoryStale = history.isStale(worksheetId); if (isHistoryStale) { System.out.println("**** REPLAY HISTORY ***"); uc.append(historyUtil.replayHistory()); worksheetId = historyUtil.getWorksheetId(); worksheet = workspace.getWorksheet(worksheetId); selection = getSuperSelection(worksheet); historyUtil = new CommandHistoryUtil(history.getCommandsFromWorksheetId(worksheetId), workspace, worksheetId); } //Execute all Provenance related commands again before publishing List<Command> wkCommands = historyUtil.getCommands(); for(Command wkCommand : wkCommands) { if(wkCommand instanceof SetSemanticTypeCommand) { SetSemanticTypeCommand cmd = (SetSemanticTypeCommand)wkCommand; if(cmd.hasProvenanceType()) { uc.append(workspace.getCommandHistory().doCommand(cmd, workspace, false)); } } else if(wkCommand instanceof AddLinkCommand) { AddLinkCommand cmd = (AddLinkCommand)wkCommand; if(cmd.hasProvenanceType()) { uc.append(workspace.getCommandHistory().doCommand(cmd, workspace, false)); } } } Set<String> inputColumns = historyUtil.generateInputColumns(); Set<String> outputColumns = historyUtil.generateOutputColumns(); JSONArray inputColumnsArray = new JSONArray(); JSONArray outputColumnsArray = new JSONArray(); for (String hNodeId : inputColumns) { HNode hnode = workspace.getFactory().getHNode(hNodeId); JSONArray hNodeRepresentation = hnode.getJSONArrayRepresentation(workspace.getFactory()); inputColumnsArray.put(hNodeRepresentation); } for (String hNodeId : outputColumns) { HNode hnode = workspace.getFactory().getHNode(hNodeId); JSONArray hNodeRepresentation = hnode.getJSONArrayRepresentation(workspace.getFactory()); outputColumnsArray.put(hNodeRepresentation); } worksheet.getMetadataContainer().getWorksheetProperties().setPropertyValue( Property.inputColumns, inputColumnsArray.toString()); worksheet.getMetadataContainer().getWorksheetProperties().setPropertyValue( Property.outputColumns, outputColumnsArray.toString()); this.worksheetName = worksheet.getTitle(); String graphLabel = worksheet.getMetadataContainer().getWorksheetProperties(). getPropertyValue(Property.graphLabel); if (graphLabel == null || graphLabel.isEmpty()) { worksheet.getMetadataContainer().getWorksheetProperties().setPropertyValue( Property.graphLabel, worksheet.getTitle()); graphLabel = worksheet.getTitle(); worksheet.getMetadataContainer().getWorksheetProperties().setPropertyValue( Property.graphName, WorksheetProperties.createDefaultGraphName(graphLabel)); } // Prepare the model file path and names final String modelFileName = graphLabel + "-model.ttl"; final String modelFileLocalPath = contextParameters.getParameterValue( ContextParameter.R2RML_PUBLISH_DIR) + modelFileName; // Get the alignment for this Worksheet Alignment alignment = AlignmentManager.Instance().getAlignment(AlignmentManager. Instance().constructAlignmentId(workspace.getId(), worksheetId)); if (alignment == null) { logger.info("Alignment is NULL for " + worksheetId); return new UpdateContainer(new ErrorUpdate( "Please align the worksheet before generating R2RML Model!")); } Set<LabeledLink> links = new HashSet<>(); if (alignment.getSteinerTree() != null) { for (LabeledLink link : alignment.getSteinerTree().edgeSet()) { if ((link.getStatus() == LinkStatus.Normal || link.getStatus() == LinkStatus.PreferredByUI) && (link.getType() == LinkType.ObjectPropertyLink)) { links.add(link); } } } //Make all links to be forced. Add a change links command for all links those links JSONArray newEdges = new JSONArray(); JSONArray initialEdges = new JSONArray(); ChangeInternalNodeLinksCommandFactory cinlcf = new ChangeInternalNodeLinksCommandFactory(); for (LabeledLink link : links) { if(link.getStatus() != LinkStatus.ForcedByUser) { JSONObject newEdge = new JSONObject(); newEdge.put(ChangeInternalNodeLinksCommand.LinkJsonKeys.edgeSourceId.name(), link.getSource().getId()); newEdge.put(ChangeInternalNodeLinksCommand.LinkJsonKeys.edgeTargetId.name(), link.getTarget().getId()); newEdge.put(ChangeInternalNodeLinksCommand.LinkJsonKeys.edgeId.name(), link.getUri()); newEdge.put(ChangeInternalNodeLinksCommand.LinkJsonKeys.isProvenance.name(), link.isProvenance()); newEdges.put(newEdge); } } JSONArray inputJSON = new JSONArray(); JSONObject t = new JSONObject(); t.put("name", "worksheetId"); t.put("type", HistoryJsonUtil.ParameterType.worksheetId.name()); t.put("value", worksheetId); inputJSON.put(t); t = new JSONObject(); t.put("name", "initialEdges"); t.put("type", HistoryJsonUtil.ParameterType.other.name()); t.put("value", initialEdges); inputJSON.put(t); t = new JSONObject(); t.put("name", "newEdges"); t.put("type", HistoryJsonUtil.ParameterType.other.name()); t.put("value", newEdges); inputJSON.put(t); if (newEdges.length() > 0 || initialEdges.length() > 0) { try { Command changeInternalNodeLinksCommand = cinlcf.createCommand(inputJSON, model, workspace); workspace.getCommandHistory().doCommand(changeInternalNodeLinksCommand, workspace); uc.add(new HistoryUpdate(workspace.getCommandHistory())); uc.append(WorksheetUpdateFactory.createRegenerateWorksheetUpdates(worksheetId, getSuperSelection(worksheet), workspace.getContextId())); uc.append(((WorksheetCommand)changeInternalNodeLinksCommand).computeAlignmentAndSemanticTypesAndCreateUpdates(workspace)); }catch(Exception e) { e.printStackTrace(); } } //Remove all provenance links that do not have Data properties Set<Node> nodes = alignment.getSteinerTree().vertexSet(); boolean linksRemoved = false; for (Node node:nodes) { if (node instanceof InternalNode) { Set<LabeledLink> outLinks = alignment.getOutgoingLinksInTree(node.getId()); if(outLinks != null && outLinks.size() > 0) { boolean hasProvLink = false; boolean hasDataProperty = false; Set<String> provLinkIds = new HashSet<>(); for(LabeledLink link : outLinks) { if(link.isProvenance()) { hasProvLink = true; provLinkIds.add(link.getId()); continue; } if(link.getType() == LinkType.DataPropertyLink) hasDataProperty = true; } if(hasProvLink && !hasDataProperty) { //Remove all provenance links for(String linkId : provLinkIds) { logger.info("**** Remove Provenance Link:" + linkId); alignment.removeLink(linkId); linksRemoved = true; } } } } } if(linksRemoved) { uc.append(WorksheetUpdateFactory.createSemanticTypesAndSVGAlignmentUpdates(worksheetId, workspace)); } // mohsen: my code to enable Karma to leran semantic models // ***************************************************************************************** // ***************************************************************************************** SemanticModel semanticModel = new SemanticModel(workspace, worksheet, worksheetName, alignment.getSteinerTree(), selection); semanticModel.setName(worksheetName); try { semanticModel.writeJson(contextParameters.getParameterValue(ContextParameter.JSON_MODELS_DIR) + semanticModel.getName() + ".model.json"); } catch (Exception e) { logger.error("error in exporting the model to JSON!"); // e.printStackTrace(); } try { semanticModel.writeGraphviz(contextParameters.getParameterValue(ContextParameter.GRAPHVIZ_MODELS_DIR) + semanticModel.getName() + ".model.dot", false, false); } catch (Exception e) { logger.error("error in exporting the model to GRAPHVIZ!"); // e.printStackTrace(); } if (modelingConfiguration.isLearnerEnabled()) ModelLearningGraph.getInstance(workspace.getOntologyManager(), ModelLearningGraphType.Compact). addModelAndUpdateAndExport(semanticModel, PatternWeightSystem.JWSPaperFormula); // ***************************************************************************************** // ***************************************************************************************** try { R2RMLAlignmentFileSaver fileSaver = new R2RMLAlignmentFileSaver(workspace); fileSaver.saveAlignment(alignment, modelFileLocalPath); // Write the model to the triple store // Get the graph name from properties String graphName = worksheet.getMetadataContainer().getWorksheetProperties() .getPropertyValue(Property.graphName); if (graphName == null || graphName.isEmpty()) { // Set to default worksheet.getMetadataContainer().getWorksheetProperties().setPropertyValue( Property.graphName, WorksheetProperties.createDefaultGraphName(worksheet.getTitle())); worksheet.getMetadataContainer().getWorksheetProperties().setPropertyValue( Property.graphLabel, worksheet.getTitle()); graphName = WorksheetProperties.createDefaultGraphName(worksheet.getTitle()); } boolean result = true;//utilObj.saveToStore(modelFileLocalPath, tripleStoreUrl, graphName, true, null); if (tripleStoreUrl != null && tripleStoreUrl.trim().compareTo("") != 0) { try { UriBuilder builder = UriBuilder.fromPath(modelFileName); String url = RESTserverAddress + "/R2RMLMapping/local/" + builder.build().toString(); SaveR2RMLModelCommandFactory factory = new SaveR2RMLModelCommandFactory(); SaveR2RMLModelCommand cmd = factory.createCommand(model, workspace, url, tripleStoreUrl, graphName, "URL"); cmd.doIt(workspace); result &= cmd.getSuccessful(); workspace.getWorksheet(worksheetId).getMetadataContainer().getWorksheetProperties().setPropertyValue(Property.modelUrl, url); workspace.getWorksheet(worksheetId).getMetadataContainer().getWorksheetProperties().setPropertyValue(Property.modelContext, graphName); workspace.getWorksheet(worksheetId).getMetadataContainer().getWorksheetProperties().setPropertyValue(Property.modelRepository, tripleStoreUrl); } catch(Exception e) { logger.error("Error pushing model to triple store", e); result = false; } } final String temp = worksheetId; uc.add(new AbstractUpdate() { public void generateJson(String prefix, PrintWriter pw, VWorkspace vWorkspace) { JSONObject outputObject = new JSONObject(); try { outputObject.put(JsonKeys.updateType.name(), "PublishR2RMLUpdate"); outputObject.put(JsonKeys.fileUrl.name(), contextParameters.getParameterValue( ContextParameter.R2RML_PUBLISH_RELATIVE_DIR) + modelFileName); outputObject.put(JsonKeys.worksheetId.name(), temp); pw.println(outputObject.toString()); } catch (JSONException e) { logger.error("Error occured while generating JSON!"); } } }); if(!result) uc.add(new TrivialErrorUpdate("Error pushing model to Triple Store")); return uc; } catch (Exception e) { logger.error("Error occured while generating R2RML Model!", e); return new UpdateContainer(new ErrorUpdate("Error occured while generating R2RML model!")); } } @Override public UpdateContainer undoIt(Workspace workspace) { // Not required return null; } private void savePreferences(Workspace workspace){ try{ JSONObject prefObject = new JSONObject(); prefObject.put(PreferencesKeys.modelSparqlEndPoint.name(), tripleStoreUrl); workspace.getCommandPreferences().setCommandPreferences( "GenerateR2RMLModelCommandPreferences", prefObject); } catch (JSONException e) { e.printStackTrace(); } } }