/// <summary> /// Obtiene los triples de un RDF /// </summary> /// <param name="pXMLRDF">XML RDF</param> /// <returns>Lista de triples</returns> public static List <string> GetTriplesFromRDF(XmlDocument pXMLRDF) { RohGraph g = new RohGraph(); g.LoadFromString(pXMLRDF.InnerXml, new RdfXmlParser()); return(GetTriplesFromGraph(g)); }
/// <summary> /// Obtiene los detalles de un rdf /// </summary> /// <returns></returns> public IActionResult DetailsRdf(Guid itemId) { //Cargamos la ontología RohGraph ontologyGraph = new RohGraph(); ontologyGraph = _callEDtlPublishService.CallGetOntology(); SparqlResultSet sparqlResultSetNombresPropiedades = (SparqlResultSet)ontologyGraph.ExecuteQuery("select distinct ?entidad ?nombre where { ?entidad <http://www.w3.org/2000/01/rdf-schema#label> ?nombre. FILTER(lang(?nombre) = 'es')}"); //Guardamos todos los nombres de las propiedades en un diccionario Dictionary <string, string> communNamePropierties = new Dictionary <string, string>(); foreach (SparqlResult sparqlResult in sparqlResultSetNombresPropiedades.Results) { communNamePropierties.Add(sparqlResult["entidad"].ToString(), ((LiteralNode)(sparqlResult["nombre"])).Value); } //Cargamos los datos DiscoverItem discoveryGraph = _discoverItemService.GetDiscoverItemById(itemId); RohGraph dataGraph = new RohGraph(); dataGraph.LoadFromString(discoveryGraph.DiscoverRdf, new RdfXmlParser()); //Guardamos todas las entidades que no son blankNodes List <String> entities = new List <string>(); SparqlResultSet sparqlResultSetListaEntidadesNotBN = (SparqlResultSet)dataGraph.ExecuteQuery("select ?s count(?p) as ?num where { ?s ?p ?o. FILTER (!isBlank(?s)) }group by ?s order by desc(?num) "); foreach (SparqlResult sparqlResult in sparqlResultSetListaEntidadesNotBN.Results) { entities.Add(sparqlResult["s"].ToString()); } List <DiscoverRdfViewModel> model = new List <DiscoverRdfViewModel>(); //Guardamos todas las entidades List <String> allEntities = new List <string>(); SparqlResultSet sparqlResultSetEntidades = (SparqlResultSet)dataGraph.ExecuteQuery("select distinct ?s where { ?s ?p ?o }"); foreach (SparqlResult sparqlResult in sparqlResultSetEntidades.Results) { allEntities.Add(sparqlResult["s"].ToString()); } SparqlResultSet sparqlResultSet = (SparqlResultSet)dataGraph.ExecuteQuery("select ?s ?p ?o where { ?s ?p ?o }"); Dictionary <string, List <SparqlResult> > entitySparqlResult = new Dictionary <string, List <SparqlResult> >(); foreach (SparqlResult sparqlResult in sparqlResultSet.Results) { if (!entitySparqlResult.ContainsKey(sparqlResult["s"].ToString())) { entitySparqlResult.Add(sparqlResult["s"].ToString(), new List <SparqlResult>()); } entitySparqlResult[sparqlResult["s"].ToString()].Add(sparqlResult); } foreach (var idEntity in entities) { DiscoverRdfViewModel entidad = createDiscoverRdfViewModel(idEntity, entitySparqlResult, new List <string>(), allEntities, communNamePropierties, discoveryGraph.LoadedEntities); model.Add(entidad); } return(View(model)); }
/// <summary> /// Crea un LiteralNode según el tipo de dato del contenido. /// </summary> /// <param name="pDataGraph">Grafo.</param> /// <param name="pContenido">Contenido del nodo.</param> /// <param name="pDatatype">Tipo del dato del contenido.</param> /// <param name="pTransform">Transformación del contenido</param> /// <returns>Nodo construido según el tipo de dato.</returns> private ILiteralNode CreateILiteralNodeType(RohGraph pDataGraph, string pContenido, string pDatatype, string pTransform = null) { pContenido = pContenido.Trim(); if (!string.IsNullOrEmpty(pTransform)) { if (pTransform.Contains("{value}")) { pContenido = pTransform.Replace("{value}", pContenido); } if (pTransform.Contains("{regex|")) { string regString = pTransform.Substring(pTransform.IndexOf("{regex|") + 7); regString = regString.Substring(0, regString.IndexOf("|endregex}")); Regex regex = new Regex(regString); Match match = regex.Match(pContenido); pContenido = pTransform.Replace("{regex|" + regString + "|endregex}", match.Value); } } if (string.IsNullOrEmpty(pDatatype)) { return(pDataGraph.CreateLiteralNode(pContenido, new Uri("http://www.w3.org/2001/XMLSchema#string"))); } else { return(pDataGraph.CreateLiteralNode(pContenido, new Uri(pDatatype))); } }
/// <summary> /// Valida un RDF /// </summary> /// <param name="pRdfFileContent">XML RDF</param> /// <param name="pShapesConfig">Lista de Shapes de validación</param> /// <returns>Lista de triples</returns> public static ShapeReport ValidateRDF(string pRdfFileContent, List <ShapeConfig> pShapesConfig) { //Cargamos la ontología RohGraph ontologyGraph = new RohGraph(); ontologyGraph.LoadFromFile("Config/Ontology/roh-v2.owl"); //Cargamos datos a validar RohGraph dataGraph = new RohGraph(); dataGraph.LoadFromString(pRdfFileContent, new RdfXmlParser()); //Aplicamos inferencias de la ontologia RohRdfsReasoner reasoner = new RohRdfsReasoner(); reasoner.Initialise(ontologyGraph); reasoner.Apply(dataGraph); ShapeReport response = new ShapeReport(); response.conforms = true; response.results = new List <ShapeReport.Result>(); foreach (ShapeConfig shape in pShapesConfig) { IGraph shapeGraph = new Graph(); shapeGraph.LoadFromString(shape.Shape); ShapesGraph shapesGraph = new ShapesGraph(shapeGraph); Report report = shapesGraph.Validate(dataGraph); if (!report.Conforms) { response.conforms = false; response.results.AddRange(report.Results.ToList().Select(x => new ShapeReport.Result() { severity = (x.Severity != null) ? x.Severity.ToString() : null, focusNode = (x.FocusNode != null) ? x.FocusNode.ToString() : null, resultValue = (x.ResultValue != null) ? x.ResultValue.ToString() : null, message = (x.Message != null) ? x.Message.ToString() : null, resultPath = (x.ResultPath != null) ? x.ResultPath.ToString() : null, shapeID = shape.ShapeConfigID, shapeName = shape.Name, sourceShape = (x.SourceShape != null) ? x.SourceShape.ToString() : null, }).ToList()); } } if (response.results.Exists(x => x.severity == "http://www.w3.org/ns/shacl#Violation")) { response.severity = "http://www.w3.org/ns/shacl#Violation"; } else if (response.results.Exists(x => x.severity == "http://www.w3.org/ns/shacl#Warning")) { response.severity = "http://www.w3.org/ns/shacl#Warning"; } else if (response.results.Exists(x => x.severity == "http://www.w3.org/ns/shacl#Info")) { response.severity = "http://www.w3.org/ns/shacl#Info"; } return(response); }
public void TestEquivalenceDiscover() { //Cargamos el RDF sobre el que aplicar el reconocimiento de enlaces RohGraph dataGraph = new RohGraph(); dataGraph.LoadFromString(System.IO.File.ReadAllText("rdfFiles/rdfFile.rdf"), new RdfXmlParser()); //TODO cargar ejemplo //Cargamos el RDF que simula la BBDD de Unidata //Si se quiere ejecutar sobre la BBDD no habría que modificar discoverUtility.mSparqlUtility y sería necesario especificar los datos del SPARQL endpoint RohGraph dataGraphBBDD = new RohGraph(); dataGraphBBDD.LoadFromString(System.IO.File.ReadAllText("rdfFiles/rdfFile.rdf"), new RdfXmlParser()); //Cargamos el RDF de la ontología RohGraph ontologyGraph = new RohGraph(); ontologyGraph.LoadFromFile("Ontology/roh-v2.owl"); //Cargamos configuraciones necesarias ConfigService ConfigService = new ConfigService(); float maxScore = ConfigService.GetMaxScore(); float minScore = ConfigService.GetMinScore(); string unidataDomain = ConfigService.GetUnidataDomain(); DiscoverUtility discoverUtility = new DiscoverUtility(); discoverUtility.mSparqlUtility = new SparqlUtilityMock(dataGraphBBDD); discoverUtility.test = true; //Aplicamos el descubrimiento de equivalencias //Los datos de configuración de SPARQL se mandan vacíos porque utilizamos el MOCK discoverUtility.ApplyEquivalenceDiscover(ref dataGraph, ontologyGraph, out Dictionary <string, Dictionary <string, float> > reconciliationEntitiesProbability, unidataDomain, minScore, maxScore, "", "", "", "", ""); }
/// <summary> /// Crea un UriNode o BlankNode a partir de una entidad. /// </summary> /// <param name="pEntidad">Entidad en cuestión.</param> /// <param name="pDataGraph">Grafo.</param> /// <returns>UriNode o BlankNode.</returns> private INode CreateINode(string pEntidad, RohGraph pDataGraph) { if (Uri.IsWellFormedUriString(pEntidad, UriKind.Absolute)) { return(pDataGraph.CreateUriNode(UriFactory.Create(pEntidad))); // UriNode. } else { return(pDataGraph.CreateBlankNode(pEntidad)); // BlankNode. } }
/// <summary> /// Constructor del resultado del descubirmiento /// </summary> /// <param name="pDataGraph">Grafo con los datos</param> /// <param name="pDataInferenceGraph">Grafo con los datos (con inferencia)</param> /// <param name="pOntologyGraph">Grafo con la ontología</param> /// <param name="pReconciliationData">Datos obtenidos de la reconciliación</param> /// <param name="pDiscoveredEntitiesProbability">Probabilidades de descubriiento</param> /// <param name="pDateStart">Fecha inicio descubirmiento</param> /// <param name="pDateEnd">Fecha fin descubirmiento</param> /// <param name="pDiscoverLinkData">Datos para trabajar con el descubrimiento de enlaces</param> public DiscoverResult(RohGraph pDataGraph, RohGraph pDataInferenceGraph, RohGraph pOntologyGraph, ReconciliationData pReconciliationData, Dictionary <string, Dictionary <string, float> > pDiscoveredEntitiesProbability, DateTime pDateStart, DateTime pDateEnd, DiscoverLinkData pDiscoverLinkData) { dataGraph = pDataGraph; dataInferenceGraph = pDataInferenceGraph; ontologyGraph = pOntologyGraph; reconciliationData = pReconciliationData; discoveredEntitiesProbability = pDiscoveredEntitiesProbability; secondsProcessed = (pDateEnd - pDateStart).TotalSeconds; start = pDateStart; end = pDateEnd; discoverLinkData = pDiscoverLinkData; }
public IActionResult dataValidate(IFormFile rdfFile, Guid repositoryIdentifier) { try { string rdfFileContent = SparqlUtility.GetTextFromFile(rdfFile); RohGraph ontologyGraph = new RohGraph(); ontologyGraph.LoadFromString(OntologyService.GetOntology()); return(Ok(SparqlUtility.ValidateRDF(rdfFileContent, _shapeConfigService.GetShapesConfigs().FindAll(x => x.RepositoryID == repositoryIdentifier), ontologyGraph))); } catch (Exception ex) { return(Problem(ex.ToString())); } }
/// <summary> /// Obtiene los triples de un RDF /// </summary> /// <param name="pXMLRDF">XML RDF</param> /// <returns>Lista de triples</returns> public static List <string> GetTriplesFromGraph(RohGraph pGraph) { List <string> triples = new List <string>(); foreach (Triple triple in pGraph.Triples) { string tripleString = ""; if (triple.Subject is BlankNode) { tripleString += triple.Subject.ToString(); } else if (triple.Subject is UriNode) { tripleString += "<" + triple.Subject.ToString() + ">"; } tripleString += " <" + ((UriNode)triple.Predicate).Uri.ToString() + ">"; if (triple.Object is LiteralNode) { Uri datatype = ((LiteralNode)triple.Object).DataType; string lang = ((LiteralNode)triple.Object).Language; if (datatype != null) { tripleString += " \"" + ((LiteralNode)triple.Object).Value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") + "\"^^<" + datatype + ">"; } else { tripleString += " \"" + ((LiteralNode)triple.Object).Value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") + "\""; } if (!string.IsNullOrEmpty(lang)) { tripleString += "@" + lang; } } else if (triple.Object is BlankNode) { tripleString += " " + triple.Object.ToString(); } else if (triple.Object is UriNode) { tripleString += " <" + triple.Object.ToString() + ">"; } tripleString += " .\r"; triples.Add(tripleString); } return(triples); }
/// <summary> /// Obtiene los triples de un RDF /// </summary> /// <param name="pXMLRDF">XML RDF</param> /// <returns>Lista de triples</returns> public static List <string> GetTriplesFromRDF(XmlDocument pXMLRDF) { RohGraph g = new RohGraph(); g.LoadFromString(pXMLRDF.InnerXml, new RdfXmlParser()); System.IO.StringWriter sw = new System.IO.StringWriter(); NTriplesWriter nTriplesWriter = new NTriplesWriter(); nTriplesWriter.Save(g, sw); return(sw.ToString().Split("\n").ToList().Select(x => Regex.Replace( x, @"\\u(?<Value>[a-zA-Z0-9]{4})", m => { return ((char)int.Parse(m.Groups["Value"].Value, NumberStyles.HexNumber)).ToString(); })).ToList()); }
/// <summary> /// Comprueba si la ontología ha cambiado. Si es así devuelve la nueva. /// </summary> /// <returns>La ontología actualizada</returns> public RohGraph CallGetOntology() { string response = _serviceApi.CallGetApi(_serviceUrl.GetUrl(), $"etl/getontologyhash", _token); if (response == hash) { return(ontologia); } else { string response2 = _serviceApi.CallGetApi(_serviceUrl.GetUrl(), $"etl/getontology", _token); ontologia = new RohGraph(); ontologia.LoadFromString(response2); hash = response; return(ontologia); } }
public IActionResult LoadOntology(IFormFile ontology) { try { OntologyService.SetOntology(ontology); string ontologyGraph = ""; ontologyGraph = _configSparql.GetGraphRoh(); RohGraph graph = new RohGraph(); graph.LoadFromString(OntologyService.GetOntology()); SparqlUtility.LoadOntology(graph, _configSparql.GetEndpoint(), _configSparql.GetQueryParam(), ontologyGraph); return(Ok()); } catch (Exception ex) { return(Problem(ex.ToString())); } }
/// <summary> /// Elimina todos los triples de la BBDD cuyo sujeto y predicado estén en el RDF a cargar y estén marcados como monovaluados. /// </summary> /// <param name="pOntologyGraph">Grafo con la ontología</param> /// <param name="pDataInferenceGraph">Grafo con los datos a cargar (con inferencia)</param> private void RemoveMonovaluatedProperties(RohGraph pOntologyGraph, RohGraph pDataInferenceGraph) { //1º Obtnemos las propiedades monovaluadas de las clases Dictionary <string, HashSet <string> > classMonovaluateProperty = new Dictionary <string, HashSet <string> >(); SparqlResultSet sparqlResultSet2 = (SparqlResultSet)pOntologyGraph.ExecuteQuery( @" select distinct ?class ?onProperty { ?class a <http://www.w3.org/2002/07/owl#Class>. { ?class <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?restriction. } UNION { ?class <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?intersection. ?intersection <http://www.w3.org/2002/07/owl#intersectionOf> ?intersectionOf. ?intersectionOf <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest>*/<http://www.w3.org/1999/02/22-rdf-syntax-ns#first> ?restriction. } ?restriction a <http://www.w3.org/2002/07/owl#Restriction>. ?restriction <http://www.w3.org/2002/07/owl#onProperty> ?onProperty. { ?restriction ?propCardinality ""1""^^<http://www.w3.org/2001/XMLSchema#nonNegativeInteger>. FILTER(?propCardinality in (<http://www.w3.org/2002/07/owl#maxQualifiedCardinality>, <http://www.w3.org/2002/07/owl#qualifiedCardinality>,<http://www.w3.org/2002/07/owl#maxCardinality>,<http://www.w3.org/2002/07/owl#cardinality>)) } }"); foreach (SparqlResult sparqlResult in sparqlResultSet2.Results) { if (!classMonovaluateProperty.ContainsKey(sparqlResult["class"].ToString())) { classMonovaluateProperty.Add(sparqlResult["class"].ToString(), new HashSet <string>()); } classMonovaluateProperty[sparqlResult["class"].ToString()].Add(sparqlResult["onProperty"].ToString()); } //2º Obtenemos del grafo a cargar los triples (con ?s ?p) de las propiedades monovaluadas Dictionary <string, HashSet <string> > entityMonovaluateProperty = new Dictionary <string, HashSet <string> >(); foreach (string clas in classMonovaluateProperty.Keys) { SparqlResultSet sparqlResultSet3 = (SparqlResultSet)pDataInferenceGraph.ExecuteQuery( @$ " select distinct ?entityID ?property {{
/// <summary> /// Obtiene los detalles de un error de descubrimiento /// </summary> /// <returns></returns> public IActionResult Details(Guid itemId) { var discovery = _discoverItemService.GetDiscoverItemById(itemId); DiscoverItemViewModel model = new DiscoverItemViewModel(); model.DissambiguationProblems = new Dictionary <string, List <string> >(); model.DissambiguationProblemsTitles = new Dictionary <string, string>(); if (discovery.Status.Equals("Error")) { model.Error = discovery.Error; model.JobId = discovery.JobID; model.IdDiscoverItem = discovery.ID; } else { RohGraph dataGraph = new RohGraph(); dataGraph.LoadFromString(discovery.DiscoverRdf, new RdfXmlParser()); model.JobId = discovery.JobID; foreach (var item in discovery.DissambiguationProblems) { model.IdDiscoverItem = item.DiscoverItemID; if (!model.DissambiguationProblems.ContainsKey(item.IDOrigin)) { model.DissambiguationProblems.Add(item.IDOrigin, new List <string>()); model.DissambiguationProblemsTitles.Add(item.IDOrigin, ""); SparqlResultSet sparqlResultSet = (SparqlResultSet)dataGraph.ExecuteQuery("select ?title where{<" + item.IDOrigin + "> ?prop ?title. FILTER(?prop in (<http://purl.org/roh#title>,<http://purl.org/roh/mirror/foaf#name>))}"); foreach (SparqlResult sparqlResult in sparqlResultSet.Results) { model.DissambiguationProblemsTitles[item.IDOrigin] = ((LiteralNode)(sparqlResult["title"])).Value; } } foreach (var problem in item.DissambiguationCandiates) { string opcion = $"{problem.IDCandidate} || {Math.Round(problem.Score, 3)}"; model.DissambiguationProblems[item.IDOrigin].Add(opcion); } } } return(View(model)); }
public void TestReconciliation() { //Cargamos el RDF sobre el que aplicar la reconciliación RohGraph dataGraph = new RohGraph(); dataGraph.LoadFromString(System.IO.File.ReadAllText("rdfFiles/rdfFileRecon.rdf"), new RdfXmlParser()); //Cargamos el RDF de la ontología RohGraph ontologyGraph = new RohGraph(); ontologyGraph.LoadFromFile("Ontology/roh-v2.owl"); //Cargamos el RDF que simula la BBDD RohGraph dataGraphBBDD = new RohGraph(); dataGraph.LoadFromString(System.IO.File.ReadAllText("rdfFiles/rdfFile.rdf"), new RdfXmlParser()); //Cargamos configuraciones necesarias ConfigService ConfigService = new ConfigService(); float maxScore = ConfigService.GetMaxScore(); float minScore = ConfigService.GetMinScore(); //Construimos el objeto DiscoverUtility DiscoverUtility discoverUtility = new DiscoverUtility(); //Sustituimos mSparqlUtility por un MOCK en el que cargamos el grafo en memoria 'dataGraphBBDD' //Si se quiere ejecutar sobre la BBDD no habría que modificar discoverUtility.mSparqlUtility y sería necesario especificar los datos del SPARQL endpoint discoverUtility.mSparqlUtility = new SparqlUtilityMock(dataGraphBBDD); discoverUtility.test = true; //Aplicamos la reconciliación //Los datos de configuración de SPARQL se mandan vacíos porque utilizamos el MOCK ReconciliationData reconciliationData = discoverUtility.ApplyReconciliation(ref dataGraph, ontologyGraph, "", "", "", "", "", minScore, maxScore, out Dictionary <string, Dictionary <string, float> > reconciliationEntitiesProbability); //En 'reconciliationData' estarán los datos que se han modificado fruto de la reconciliación //En 'dataGraph' estará el grafo modificado tras la reconciliación //En 'reconciliationEntitiesProbability' estarán las entidades para las que ha habido problemas de desambiguación }
/// <summary> /// Carga una ontología en un SPARQL endpoint /// </summary> /// <param name="pOntology">Ontología</param> /// <param name="pSPARQLEndpoint">Endpoint SPARQL</param> /// <param name="pQueryParam">Query param</param> /// <param name="pGraph">Grafo</param> public static void LoadOntology(RohGraph pOntology, string pSPARQLEndpoint, string pQueryParam, string pGraph) { //Eliminamos los datos anteriores string query = ""; query += $" clear graph <{pGraph}>"; string url = pSPARQLEndpoint; NameValueCollection parametros = new NameValueCollection(); parametros.Add(pQueryParam, query); WebClient webClient = new WebClient(); try { webClient.UploadValues(url, "POST", parametros); } catch (WebException ex) { if (ex.Response != null) { string response = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd(); throw new Exception(response); } throw ex; } catch (Exception ex) { throw ex; } finally { webClient.Dispose(); } //Cargamos la ontología SparqlUtility.LoadTriples(SparqlUtility.GetTriplesFromGraph(pOntology), pSPARQLEndpoint, pQueryParam, pGraph); }
/// <summary> /// Elimina los triples http://purl.org/roh/mirror/foaf#primaryTopic del RDF a cargar y los triples que tenían cagados en la BBDD /// </summary> /// <param name="pDataGraph">Grafo con los datos a cargar</param> /// <returns>Lista de grafos afectados</returns> private HashSet <string> RemovePrimaryTopics(ref RohGraph pDataGraph) { HashSet <string> graphs = new HashSet <string>(); List <string> mainEntities = new List <string>(); string query = @"select distinct * where{?s <http://purl.org/roh/mirror/foaf#primaryTopic> ""true""^^<http://www.w3.org/2001/XMLSchema#boolean>}"; SparqlResultSet sparqlResultSet = (SparqlResultSet)pDataGraph.ExecuteQuery(query.ToString()); foreach (SparqlResult sparqlResult in sparqlResultSet.Results) { mainEntities.Add(sparqlResult["s"].ToString()); } //Se eliminan todas las referncias a las entidades principales if (mainEntities.Count > 0) { foreach (string mainEntity in mainEntities) { graphs.UnionWith(DeleteUpdatedEntity(mainEntity)); } } //Eliminamos el triple que marca las entidades principales para que no se inserte en la BBDD { TripleStore store = new TripleStore(); store.Add(pDataGraph); SparqlUpdateParser parser = new SparqlUpdateParser(); //Actualizamos los sujetos SparqlUpdateCommandSet updateSubject = parser.ParseFromString( @" DELETE { ?s ?p ?o. } WHERE { ?s ?p ?o. FILTER(?p =<http://purl.org/roh/mirror/foaf#primaryTopic>) }"); LeviathanUpdateProcessor processor = new LeviathanUpdateProcessor(store); processor.ProcessCommandSet(updateSubject); } return(graphs); }
public void TestDiscoverLinks() { //Cargamos el RDF sobre el que aplicar el reconocimiento de enlaces RohGraph dataGraph = new RohGraph(); dataGraph.LoadFromString(System.IO.File.ReadAllText("rdfFiles/rdfFile.rdf"), new RdfXmlParser()); //Cargamos el RDF de la ontología RohGraph ontologyGraph = new RohGraph(); ontologyGraph.LoadFromFile("Ontology/roh-v2.owl"); DiscoverUtility discoverUtility = new DiscoverUtility(); discoverUtility.test = true; CallUrisFactoryApiMockService callUrisFactoryApiMockService = new CallUrisFactoryApiMockService(); //Aplicamos el descubrimiento de enlaces Dictionary <string, List <DiscoverLinkData.PropertyData> > discoverLinks = discoverUtility.ApplyDiscoverLinks(ref dataGraph, ontologyGraph, 0.7f, 0.9f, "", "", "HerculesASIO-University-of-Murcia (https://github.com/HerculesCRUE/GnossDeustoBackend; mailto:<mail>) AsioBot", "Basic czAzNjkuZmVjeXQuZXM6VTQ5RDhSWU40d3Mh", callUrisFactoryApiMockService); //En 'discoverLinks' estarán los datos que se han recuperado de las integraciones externas junto con su provenance //En 'dataGraph' estará el grafo modificado tras el descubrimiento de enlaces }
/// <summary> /// Procesa los resultados del descubrimiento /// </summary> /// <param name="pDiscoverItem">Objeto con los datos de com procesar el proeso de descubrimiento</param> /// <param name="pDiscoverResult">Resultado de la aplicación del descubrimiento</param> /// <param name="pDiscoverItemBDService">Clase para gestionar las operaciones de las tareas de descubrimiento</param> /// <param name="pCallCronApiService">Servicio para hacer llamadas a los métodos del apiCron</param> /// <param name="pCallUrisFactoryApiService">Servicio para hacer llamadas a los métodos del Uris Factory</param> /// <param name="pProcessDiscoverStateJobBDService">Clase para gestionar los estados de descubrimiento de las tareas</param> /// <returns></returns> public void Process(DiscoverItem pDiscoverItem, DiscoverResult pDiscoverResult, DiscoverItemBDService pDiscoverItemBDService, CallCronApiService pCallCronApiService, CallUrisFactoryApiService pCallUrisFactoryApiService, ProcessDiscoverStateJobBDService pProcessDiscoverStateJobBDService) { #region Cargamos configuraciones ConfigSparql ConfigSparql = new ConfigSparql(); string SGI_SPARQLEndpoint = ConfigSparql.GetEndpoint(); string SGI_SPARQLGraph = ConfigSparql.GetGraph(); string SGI_SPARQLQueryParam = ConfigSparql.GetQueryParam(); string SGI_SPARQLUsername = ConfigSparql.GetUsername(); string SGI_SPARQLPassword = ConfigSparql.GetPassword(); string Unidata_SPARQLEndpoint = ConfigSparql.GetUnidataEndpoint(); string Unidata_SPARQLGraph = ConfigSparql.GetUnidataGraph(); string Unidata_SPARQLQueryParam = ConfigSparql.GetUnidataQueryParam(); string Unidata_SPARQLUsername = ConfigSparql.GetUnidataUsername(); string Unidata_SPARQLPassword = ConfigSparql.GetUnidataPassword(); ConfigService ConfigService = new ConfigService(); string UnidataDomain = ConfigService.GetUnidataDomain(); string UnidataUriTransform = ConfigService.GetUnidataUriTransform(); #endregion /* * En función del resultado obtenido se realiza una de las siguientes acciones: * Si para alguna entidad hay más de un candidato que supere el umbral máximo o hay alguna entidad que supere el umbral mínimo pero no alcance el máximo se agregará el RDF a una BBDD junto con todos los datos necesarios para que el administrador decida como proceder. * Si no estamos en el punto anterior * Se obtienen las entidades principales del RDF y se eliminan todos los triples que haya en la BBDD en los que aparezcan como sujeto u objeto. * Se eliminan todos los triples cuyo sujeto y predicado estén en el RDF a cargar y estén marcados como monovaluados. * Se vuelcan los triples a la BBDD. * * */ if (pDiscoverItem.Publish) { if (pDiscoverResult.discoveredEntitiesProbability.Count > 0) { //Hay dudas en la desambiguación, por lo que lo actualizamos en la BBDD con su estado correspondiente pDiscoverItem.UpdateDissambiguationProblems( pDiscoverResult.discoveredEntitiesProbability, pDiscoverResult.reconciliationData.reconciliatedEntitiesWithBBDD.Values.Select(x => x.uri).Union(pDiscoverResult.reconciliationData.reconciliatedEntitiesWithIds.Values).Union(pDiscoverResult.reconciliationData.reconciliatedEntitiesWithSubject).Union(pDiscoverResult.reconciliationData.reconciliatedEntitiesWithExternalIntegration.Values.Select(x => x.uri)).ToList(), pDiscoverResult.GetDataGraphRDF()); pDiscoverItemBDService.ModifyDiscoverItem(pDiscoverItem); } else { string urlDiscoverAgent = pCallUrisFactoryApiService.GetUri("Agent", "discover"); //Creamos los SameAs hacia unidata para las entidades que NO lo tengan hacia Unidata //TODO descomentar cuando esté habilitaado Unidata //pDiscoverResult.dataGraph = AsioPublication.CreateUnidataSameAs(pDiscoverResult.dataGraph, UnidataDomain, UnidataUriTransform); //Publicamos en el SGI AsioPublication asioPublication = new AsioPublication(SGI_SPARQLEndpoint, SGI_SPARQLQueryParam, SGI_SPARQLGraph, SGI_SPARQLUsername, SGI_SPARQLPassword); asioPublication.PublishRDF(pDiscoverResult.dataGraph, pDiscoverResult.ontologyGraph, new KeyValuePair <string, string>(urlDiscoverAgent, "Algoritmos de descubrimiento"), pDiscoverResult.start, pDiscoverResult.end, pDiscoverResult.discoverLinkData, pCallUrisFactoryApiService); //TODO Lógica nombres de personas SparqlResultSet sparqlResultSet = (SparqlResultSet)pDiscoverResult.dataGraph.ExecuteQuery("select ?s ?name where {?s a <http://purl.org/roh/mirror/foaf#Person>. ?s <http://purl.org/roh/mirror/foaf#name> ?name}"); foreach (SparqlResult sparqlResult in sparqlResultSet.Results) { string s = sparqlResult["s"].ToString(); string nombre = sparqlResult["name"].ToString(); if (sparqlResult["name"] is ILiteralNode) { nombre = ((ILiteralNode)sparqlResult["name"]).Value; } _discoverCacheGlobal.PersonsNormalizedNames[s] = DiscoverUtility.NormalizeName(nombre); } //TODO Lógica titles SparqlResultSet sparqlResultSetTitles = (SparqlResultSet)pDiscoverResult.dataGraph.ExecuteQuery("select * where {?s a ?rdftype. ?s <http://purl.org/roh#title> ?title}"); foreach (SparqlResult sparqlResult in sparqlResultSetTitles.Results) { string s = sparqlResult["s"].ToString(); string rdftype = sparqlResult["rdftype"].ToString(); string title = sparqlResult["title"].ToString(); if (sparqlResult["title"] is ILiteralNode) { title = ((ILiteralNode)sparqlResult["title"]).Value; } title = DiscoverUtility.NormalizeTitle(title); if (!_discoverCacheGlobal.EntitiesNormalizedTitles.ContainsKey(rdftype)) { _discoverCacheGlobal.EntitiesNormalizedTitles.Add(rdftype, new Dictionary <string, HashSet <string> >()); } if (!_discoverCacheGlobal.EntitiesNormalizedTitles[rdftype].ContainsKey(title)) { _discoverCacheGlobal.EntitiesNormalizedTitles[rdftype].Add(title, new HashSet <string>()); } _discoverCacheGlobal.EntitiesNormalizedTitles[rdftype][title].Add(s); } //TODO descomentar cuando esté habilitaado Unidata if (false) { //Publicamos en UNIDATA AsioPublication asioPublicationUnidata = new AsioPublication(Unidata_SPARQLEndpoint, Unidata_SPARQLQueryParam, Unidata_SPARQLGraph, Unidata_SPARQLUsername, Unidata_SPARQLPassword); // Prepara el grafo para su carga en Unidata, para ello coge las URIs de Unidata del SameAs y la aplica a los sujetos y los antiguos sujetos se agregan al SameAs RohGraph unidataGraph = AsioPublication.TransformUrisToUnidata(pDiscoverResult.dataGraph, UnidataDomain, UnidataUriTransform); //Eliminamos los triples de crisIdentifier ya que no hay que volcarlos en unidata { TripleStore store = new TripleStore(); store.Add(unidataGraph); SparqlUpdateParser parser = new SparqlUpdateParser(); //Actualizamos los sujetos SparqlUpdateCommandSet updateSubject = parser.ParseFromString( @" DELETE { ?s ?p ?o. } WHERE { ?s ?p ?o. FILTER(?p =<" + mPropertySGIRohCrisIdentifier + @">) }"); LeviathanUpdateProcessor processor = new LeviathanUpdateProcessor(store); processor.ProcessCommandSet(updateSubject); } asioPublicationUnidata.PublishRDF(unidataGraph, pDiscoverResult.ontologyGraph, new KeyValuePair <string, string>(urlDiscoverAgent, "Algoritmos de descubrimiento"), pDiscoverResult.start, pDiscoverResult.end, pDiscoverResult.discoverLinkData, pCallUrisFactoryApiService); } //Lo marcamos como procesado en la BBDD y eliminamos sus metadatos pDiscoverItem.UpdateProcessed(); pDiscoverItemBDService.ModifyDiscoverItem(pDiscoverItem); } //Actualizamos el estado de descubrimiento de la tarea si el estado encolado esta en estado Succeeded o Failed (ha finalizado) //TODO cambiar por query a BBDD string statusQueueJob = pCallCronApiService.GetJob(pDiscoverItem.JobID).State; if ((statusQueueJob == "Failed" || statusQueueJob == "Succeeded")) { ProcessDiscoverStateJob processDiscoverStateJob = pProcessDiscoverStateJobBDService.GetProcessDiscoverStateJobByIdJob(pDiscoverItem.JobID); string state; //Actualizamos a error si existen items en estado error o con problemas de desambiguación if (pDiscoverItemBDService.ExistsDiscoverItemsErrorOrDissambiguatinProblems(pDiscoverItem.JobID)) { state = "Error"; } else if (pDiscoverItemBDService.ExistsDiscoverItemsPending(pDiscoverItem.JobID)) { //Actualizamos a 'Pending' si aún existen items pendientes state = "Pending"; } else { //Actualizamos a Success si no existen items en estado error ni con problemas de desambiguación y no hay ninguno pendiente state = "Success"; } if (processDiscoverStateJob != null) { processDiscoverStateJob.State = state; pProcessDiscoverStateJobBDService.ModifyProcessDiscoverStateJob(processDiscoverStateJob); } else { processDiscoverStateJob = new ProcessDiscoverStateJob() { State = state, JobId = pDiscoverItem.JobID }; pProcessDiscoverStateJobBDService.AddProcessDiscoverStateJob(processDiscoverStateJob); } } } else { //Actualizamos en BBDD DiscoverItem discoverItemBD = pDiscoverItemBDService.GetDiscoverItemById(pDiscoverItem.ID); //Reporte de descubrimiento string discoverReport = "Time processed (seconds): " + pDiscoverResult.secondsProcessed + "\n"; if (pDiscoverResult.reconciliationData.reconciliatedEntitiesWithSubject != null && pDiscoverResult.reconciliationData.reconciliatedEntitiesWithSubject.Count > 0) { discoverReport += "Entities discover with the same uri: " + pDiscoverResult.reconciliationData.reconciliatedEntitiesWithSubject.Count + "\n"; foreach (string uri in pDiscoverResult.reconciliationData.reconciliatedEntitiesWithSubject) { discoverReport += "\t" + uri + "\n"; } } if (pDiscoverResult.reconciliationData.reconciliatedEntitiesWithIds != null && pDiscoverResult.reconciliationData.reconciliatedEntitiesWithIds.Count > 0) { discoverReport += "Entities discover with some common identifier: " + pDiscoverResult.reconciliationData.reconciliatedEntitiesWithIds.Count + "\n"; foreach (string uri in pDiscoverResult.reconciliationData.reconciliatedEntitiesWithIds.Keys) { discoverReport += "\t" + uri + " --> " + pDiscoverResult.reconciliationData.reconciliatedEntitiesWithIds[uri] + "\n"; } } if (pDiscoverResult.reconciliationData.reconciliatedEntitiesWithBBDD != null && pDiscoverResult.reconciliationData.reconciliatedEntitiesWithBBDD.Count > 0) { discoverReport += "Entities discover with reconciliation config: " + pDiscoverResult.reconciliationData.reconciliatedEntitiesWithBBDD.Count + "\n"; foreach (string uri in pDiscoverResult.reconciliationData.reconciliatedEntitiesWithBBDD.Keys) { discoverReport += "\t" + uri + " --> " + pDiscoverResult.reconciliationData.reconciliatedEntitiesWithBBDD[uri] + "\n"; } } if (pDiscoverResult.reconciliationData.reconciliatedEntitiesWithExternalIntegration != null && pDiscoverResult.reconciliationData.reconciliatedEntitiesWithExternalIntegration.Count > 0) { discoverReport += "Entities discover with external integrations config: " + pDiscoverResult.reconciliationData.reconciliatedEntitiesWithExternalIntegration.Count + "\n"; foreach (string uri in pDiscoverResult.reconciliationData.reconciliatedEntitiesWithExternalIntegration.Keys) { discoverReport += "\t" + uri + " --> " + pDiscoverResult.reconciliationData.reconciliatedEntitiesWithExternalIntegration[uri] + "\n"; } } if (pDiscoverResult.discoverLinkData != null && pDiscoverResult.discoverLinkData.entitiesProperties != null && pDiscoverResult.discoverLinkData.entitiesProperties.Count > 0) { discoverReport += "Entities with identifiers obtained with External integration: " + pDiscoverResult.discoverLinkData.entitiesProperties.Count + "\n"; foreach (string uri in pDiscoverResult.discoverLinkData.entitiesProperties.Keys) { foreach (DiscoverLinkData.PropertyData property in pDiscoverResult.discoverLinkData.entitiesProperties[uri]) { foreach (string value in property.valueProvenance.Keys) { foreach (string provenance in property.valueProvenance[value]) { discoverReport += "\t" + uri + " - " + property.property + " - " + value + " --> " + provenance + "\n"; } } } } } discoverItemBD.UpdateReport(pDiscoverResult.discoveredEntitiesProbability, pDiscoverResult.GetDataGraphRDF(), discoverReport); pDiscoverItemBDService.ModifyDiscoverItem(discoverItemBD); } }
/// <summary> /// Crea todas las entidades ontológicas del XML. /// </summary> /// <param name="pDataGraph">Grafo.</param> /// <param name="pLista">Lista de entidades.</param> /// <param name="pNodo">Nodo del que se va a hacer la búsqueda.</param> /// <param name="pNsmgr">Namespace del nodo.</param> /// <returns>Lista de entidades.</returns> private List <string> CreateEntities(RohGraph pDataGraph, Entity[] pLista, XmlNode pNodo, XmlNamespaceManager pNsmgr) { List <string> listaEntities = new List <string>(); if (pLista != null) { foreach (Entity entidad in pLista) { // Si está vacío, no genera el namespace. if (!string.IsNullOrEmpty(entidad.nameSpace)) { pNsmgr.AddNamespace("ns", entidad.nameSpace); } List <XmlNode> listaEntidades = new List <XmlNode>(); if (string.IsNullOrEmpty(entidad.source)) { listaEntidades.Add(pNodo); } else { listaEntidades = new List <XmlNode>(pNodo.SelectNodes(entidad.source, pNsmgr).Cast <XmlNode>()); } foreach (XmlNode nodo in listaEntidades) { // Comprobar si un hijo en concreto está vacío o no. bool tieneHijoComprobado = true; if (!string.IsNullOrEmpty(entidad.comprobarSubentidad)) { tieneHijoComprobado = false; foreach (XmlNode child in nodo.ChildNodes) { if (child.Name == entidad.comprobarSubentidad) { tieneHijoComprobado = true; } } } if (nodo.ChildNodes.Count > 0 && tieneHijoComprobado == true) { // Entidades. string uriEntity = GetURI(entidad, nodo, pNsmgr); // Obtención del URI. listaEntities.Add(uriEntity); INode sujeto = CreateINode(uriEntity, pDataGraph); // Creación de UriNode o BlankNode. INode propRdftype = pDataGraph.CreateUriNode(UriFactory.Create("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")); INode rdfType; if (entidad.rdftype != null) { rdfType = pDataGraph.CreateUriNode(UriFactory.Create(entidad.rdftype)); } else { if (entidad.rdftypeproperty != null) { rdfType = pDataGraph.CreateUriNode(UriFactory.Create(GetTarget(entidad, nodo, pNsmgr))); } else { throw new Exception("No se ha podido obtener el rdf:type de la entidad: " + nodo.Name); } } pDataGraph.Assert(new Triple(sujeto, propRdftype, rdfType)); // Creación del Triple. // --- Propiedades. // Si es la entidad inicial, se le agrega un triple en concreto. if (entidad.mainEntity) { IUriNode predicado = pDataGraph.CreateUriNode(UriFactory.Create("http://purl.org/roh/mirror/foaf#primaryTopic")); ILiteralNode objeto = CreateILiteralNodeType(pDataGraph, "true", "http://www.w3.org/2001/XMLSchema#boolean"); pDataGraph.Assert(new Triple(sujeto, predicado, objeto)); // Creación del Triple. } if (entidad.property != null) { INode prop = pDataGraph.CreateUriNode(UriFactory.Create(entidad.property)); INode val = CreateILiteralNodeType(pDataGraph, nodo.InnerText, entidad.datatype, entidad.transform); pDataGraph.Assert(new Triple(sujeto, prop, val)); // Creación del Triple. } if (entidad.properties != null) { foreach (Property propiedad in entidad.properties) { string value = string.Empty; if (string.IsNullOrEmpty(propiedad.source)) { value = nodo.InnerText; } else { foreach (string source in propiedad.source.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries)) { if (!string.IsNullOrEmpty(entidad.nameSpace)) { pNsmgr.AddNamespace("ns", entidad.nameSpace); } XmlNode node = nodo.SelectSingleNode(source, pNsmgr); if (node != null) { value += " " + node.InnerText; } } } value = value.Trim(); if (!string.IsNullOrEmpty(value)) { IUriNode predicado = pDataGraph.CreateUriNode(UriFactory.Create(propiedad.property)); ILiteralNode objeto = CreateILiteralNodeType(pDataGraph, value, propiedad.datatype, propiedad.transform); pDataGraph.Assert(new Triple(sujeto, predicado, objeto)); // Creación del Triple. } } } // --- Subentidades. if (entidad.subentities != null) { foreach (Subentity subentity in entidad.subentities) { List <string> listado = CreateEntities(pDataGraph, subentity.entities, nodo, pNsmgr); // Método recursivo. int numSeq = 1; // Número de la secuencia. foreach (string ent in listado) { string property = subentity.property; // Si el rdftype es de tipo secuencia, crea la propiedad + número de Seq. if (entidad.rdftype == "http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq") { property = "http://www.w3.org/1999/02/22-rdf-syntax-ns#_" + numSeq; } INode objeto = CreateINode(ent, pDataGraph); // Propiedad Directa. if (!string.IsNullOrEmpty(property)) { INode predicado = pDataGraph.CreateUriNode(UriFactory.Create(property)); pDataGraph.Assert(new Triple(sujeto, predicado, objeto)); // Creación del Triple. } // Propiedad Inversa. if (!string.IsNullOrEmpty(subentity.inverseProperty)) { INode predicadoInverso = pDataGraph.CreateUriNode(UriFactory.Create(subentity.inverseProperty)); pDataGraph.Assert(new Triple(objeto, predicadoInverso, sujeto)); // Creación del Triple. } numSeq++; } } } } } } } return(listaEntities); }
/// <summary> /// Publica un RDF en Asio aplicado todos losprocedimientos pertinentes /// </summary> /// <param name="pDataGraph">Grafo con los datos a cargar</param> /// <param name="pOntologyGraph">Grafo con la ontología</param> /// <param name="pAttributedTo">Sujeto y nombre para atribuir los triples de los apis externos</param> /// <param name="pActivityStartedAtTime">Inicio del proceso</param> /// <param name="pActivityEndedAtTime">Fin del proceso</param> /// <param name="pDiscoverLinkData">Datos para trabajar con el descubrimiento de enlaces</param> /// <param name="pCallUrisFactoryApiService">Servicio para hacer llamadas a los métodos del Uris Factory</param> public void PublishRDF(RohGraph pDataGraph, RohGraph pOntologyGraph, KeyValuePair <string, string>?pAttributedTo, DateTime pActivityStartedAtTime, DateTime pActivityEndedAtTime, DiscoverLinkData pDiscoverLinkData, CallUrisFactoryApiService pCallUrisFactoryApiService) { RohGraph inferenceDataGraph = null; if (pOntologyGraph != null) { inferenceDataGraph = pDataGraph.Clone(); RohRdfsReasoner reasoner = new RohRdfsReasoner(); reasoner.Initialise(pOntologyGraph); reasoner.Apply(inferenceDataGraph); } // 1º Eliminamos de la BBDD las entidades principales que aparecen en el RDF HashSet <string> graphs = RemovePrimaryTopics(ref pDataGraph); graphs.Add(_Graph); // 2º Eliminamos todos los triples de la BBDD cuyo sujeto y predicado estén en el RDF a cargar y estén marcados como monovaluados. if (pOntologyGraph != null && inferenceDataGraph != null) { RemoveMonovaluatedProperties(pOntologyGraph, inferenceDataGraph); } //3º Insertamos los triples en la BBDD if (pAttributedTo.HasValue) { //Añadimos triples del softwareagent IUriNode t_subject = pDataGraph.CreateUriNode(UriFactory.Create(pAttributedTo.Value.Key)); IUriNode t_predicate_rdftype = pDataGraph.CreateUriNode(UriFactory.Create("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")); IUriNode t_object_rdftype = pDataGraph.CreateUriNode(UriFactory.Create("http://www.w3.org/ns/prov#SoftwareAgent")); pDataGraph.Assert(new Triple(t_subject, t_predicate_rdftype, t_object_rdftype)); IUriNode t_predicate_name = pDataGraph.CreateUriNode(UriFactory.Create("http://purl.org/roh/mirror/foaf#name")); ILiteralNode t_object_name = pDataGraph.CreateLiteralNode(pAttributedTo.Value.Value, new Uri("http://www.w3.org/2001/XMLSchema#string")); pDataGraph.Assert(new Triple(t_subject, t_predicate_name, t_object_name)); } SparqlUtility.LoadTriples(SparqlUtility.GetTriplesFromGraph(pDataGraph), _SPARQLEndpoint, _QueryParam, _Graph, _Username, _Password); //4º Insertamos los triples con provenance en la BBDD if (pDiscoverLinkData != null && pDiscoverLinkData.entitiesProperties != null) { Dictionary <string, List <string> > graphDeletes = new Dictionary <string, List <string> >(); Dictionary <string, List <string> > graphTriples = new Dictionary <string, List <string> >(); foreach (string t_subject in pDiscoverLinkData.entitiesProperties.Keys) { foreach (DiscoverLinkData.PropertyData property in pDiscoverLinkData.entitiesProperties[t_subject]) { string t_property = property.property; foreach (var prop in property.valueProvenance) { string t_object = prop.Key; HashSet <string> t_sourceids = prop.Value; foreach (string sourceId in t_sourceids) { string graph = pCallUrisFactoryApiService.GetUri("Graph", sourceId); if (!graphTriples.ContainsKey(graph)) { graphTriples.Add(graph, new List <string>()); } string bNodeid = "_:" + Guid.NewGuid().ToString(); graphTriples[graph].Add($@"<{t_subject}> <http://www.w3.org/ns/prov#wasUsedBy> {bNodeid} ."); graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/ns/prov#Activity> ."); graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <{t_property}>."); if (Uri.IsWellFormedUriString(t_object, UriKind.Absolute)) { graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <{ t_object}>."); } else { graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/1999/02/22-rdf-syntax-ns#object> ""{ t_object.Replace("\"", "\\\"").Replace("\n", "\\n") }""^^<http://www.w3.org/2001/XMLSchema#string>."); } graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/ns/prov#startedAtTime> ""{ pActivityStartedAtTime.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz") }""^^<http://www.w3.org/2001/XMLSchema#datetime>."); graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/ns/prov#endedAtTime> ""{ pActivityEndedAtTime.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz") }""^^<http://www.w3.org/2001/XMLSchema#datetime>."); graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/ns/prov#wasAssociatedWith> <{pAttributedTo.Value.Key}>."); graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/ns/prov#wasAssociatedWith> <{pCallUrisFactoryApiService.GetUri("http://purl.org/roh/mirror/foaf#Organization", sourceId)}>."); if (pAttributedTo.HasValue) { graphTriples[graph].Add($@"{bNodeid} <http://www.w3.org/ns/prov#wasAssociatedWith> <{pAttributedTo.Value.Key}>."); } if (!graphDeletes.ContainsKey(graph)) { graphDeletes.Add(graph, new List <string>()); } if (!Uri.IsWellFormedUriString(t_object, UriKind.Absolute)) { string stringDelete = $@" {{ ?s ?p ?o. ?o <http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <{t_property}>. ?o <http://www.w3.org/1999/02/22-rdf-syntax-ns#object> ""{ t_object.Replace("\"", "\\\"").Replace("\n", "\\n") }""^^<http://www.w3.org/2001/XMLSchema#string>. FILTER(?s = <{t_subject}>) }}"; graphDeletes[graph].Add(stringDelete); } } } } } //Eliminamos aquellos triples de provenance que ya estén cargados foreach (string graph in graphDeletes.Keys) { graphs.Add(graph); string queryDeleteProvenance = $@" DELETE {{ ?s ?p ?o. }} WHERE {{ {{{string.Join("}UNION{", graphDeletes[graph])}}} }}"; _SparqlUtility.SelectData(_SPARQLEndpoint, graph, queryDeleteProvenance, _QueryParam, _Username, _Password); } //Cargamos los nuevos triples foreach (string graph in graphTriples.Keys) { SparqlUtility.LoadTriples(graphTriples[graph], _SPARQLEndpoint, _QueryParam, graph, _Username, _Password); } } //5º Limpiamos los blanknodes huerfanos, o que no tengan triples //TODO mover a una tarea que se ejecute continuamente //DeleteOrphanNodes(graphs); }
public IActionResult Convert(IFormFile pXmlFile, string pType) { try { // Ruta del fichero de configuración JSON. string rutaJson = String.Empty; List <string> listaConfiguraciones = ConfigFilesList(); if (listaConfiguraciones.Contains(pType)) { rutaJson = "Config/" + pType + ".json"; } else { return(Problem("El fichero de configuración JSON no existe.")); } // Conversión a JSON. ConversorConfig objJson = JsonConvert.DeserializeObject <ConversorConfig>(System.IO.File.ReadAllText(rutaJson)); // Lectura del archivo XML. StringBuilder resultXml = new StringBuilder(); using (StreamReader reader = new StreamReader(pXmlFile.OpenReadStream())) { while (reader.Peek() >= 0) { resultXml.AppendLine(reader.ReadLine()); } } string ficheroXml = resultXml.ToString(); // Conversión a XML. XmlDocument documento = new XmlDocument(); documento.LoadXml(ficheroXml); // Namespace. XmlNamespaceManager nsmgr = new XmlNamespaceManager(documento.NameTable); // Creación del RDF virtual. RohGraph dataGraph = new RohGraph(); CreateEntities(dataGraph, objJson.entities, documento, nsmgr); // Método Recursivo. // Consulta de comprobación. Object consulta = dataGraph.ExecuteQuery("SELECT * WHERE {?s ?p ?o}"); // Creación del RDF. System.IO.StringWriter sw = new System.IO.StringWriter(); RdfXmlWriter rdfXmlWriter = new RdfXmlWriter(); rdfXmlWriter.Save(dataGraph, sw); // Comprobación RDF. string graphRDF = sw.ToString(); // Obtener RDF. byte[] array = Encoding.UTF8.GetBytes(graphRDF); return(File(array, "application/rdf+xml")); } catch (Exception ex) { return(Problem(ex.ToString())); } }
public SparqlUtilityMock(RohGraph dataGraph) { _dataGraph = dataGraph; }
public IActionResult Index() { //Obtenemos la URL de la entidad string url = Request.GetEncodedUrl(); //string url = Request.GetDisplayUrl(); string urlParam = HttpUtility.ParseQueryString(Request.QueryString.Value).Get("url"); if (!string.IsNullOrEmpty(urlParam)) { url = urlParam; } ViewBag.UrlHome = mConfigService.GetUrlHome(); //Customizamos Header if (!string.IsNullOrEmpty(mConfigService.GetConstrainedByUrl())) { HttpContext.Response.Headers.Add("Link", "<http://www.w3.org/ns/ldp#BasicContainer>; rel=\"type\", <http://www.w3.org/ns/ldp#Resource>; rel=\"type\", <" + mConfigService.GetConstrainedByUrl() + ">; rel=\"http://www.w3.org/ns/ldp#constrainedBy\""); } else { HttpContext.Response.Headers.Add("Link", "<http://www.w3.org/ns/ldp#BasicContainer>; rel=\"type\", <http://www.w3.org/ns/ldp#Resource>; rel=\"type\""); } HashSet <string> methodsAvailable = new HashSet <string>() { "GET", "HEAD", "OPTIONS" }; HttpContext.Response.Headers.Add("allow", string.Join(", ", methodsAvailable)); if (!methodsAvailable.Contains(Request.HttpContext.Request.Method)) { return(StatusCode(StatusCodes.Status405MethodNotAllowed)); } //Cargamos la ontología RohGraph ontologyGraph = LoadGraph(mConfigService.GetOntologyGraph()); SparqlResultSet sparqlResultSetNombresPropiedades = (SparqlResultSet)ontologyGraph.ExecuteQuery(@"select distinct ?entidad ?nombre lang(?nombre) as ?lang where { ?entidad <http://www.w3.org/2000/01/rdf-schema#label> ?nombre. }"); //Guardamos todos los nombres de las propiedades en un diccionario Dictionary <string, string> communNamePropierties = new Dictionary <string, string>(); foreach (SparqlResult sparqlResult in sparqlResultSetNombresPropiedades.Results) { string entity = sparqlResult["entidad"].ToString(); if (!communNamePropierties.ContainsKey(entity)) { List <SparqlResult> filas = sparqlResultSetNombresPropiedades.Results.Where(x => x["entidad"].ToString() == entity).ToList(); if (filas.FirstOrDefault(x => x["lang"].ToString() == "es") != null) { communNamePropierties[entity] = ((LiteralNode)filas.FirstOrDefault(x => x["lang"].ToString() == "es")["nombre"]).Value.ToString(); } else if (filas.FirstOrDefault(x => x["lang"].ToString() == "en") != null) { communNamePropierties[entity] = ((LiteralNode)filas.FirstOrDefault(x => x["lang"].ToString() == "en")["nombre"]).Value.ToString(); } else if (filas.FirstOrDefault(x => string.IsNullOrEmpty(x["lang"].ToString())) != null) { communNamePropierties[entity] = ((LiteralNode)filas.FirstOrDefault(x => string.IsNullOrEmpty(x["lang"].ToString()))["nombre"]).Value.ToString(); } } } //Cargamos las entidades propias Dictionary <string, string> entitiesNames; Dictionary <string, SparqlObject> sparqlObjectDictionary = GetEntityData(url, out entitiesNames); if (sparqlObjectDictionary.Count == 1 && sparqlObjectDictionary[url].results.bindings.Count == 0) { //No existe la entidad HttpContext.Response.StatusCode = 404; ViewData["Title"] = "Error 404 página no encontrada para la entidad " + url; ViewData["NameTitle"] = mConfigService.GetNameTitle(); return(View(new EntityModelTemplate())); } else { //Cargamos los datos en un grafo en Local RohGraph dataGraph = new RohGraph(); createDataGraph(url, new List <string>(), false, dataGraph, sparqlObjectDictionary); //Generamos el RDF System.IO.StringWriter sw = new System.IO.StringWriter(); RdfXmlWriter rdfXmlWriter = new RdfXmlWriter(); rdfXmlWriter.Save(dataGraph, sw); string rdf = sw.ToString(); Microsoft.Extensions.Primitives.StringValues stringvalues; HttpContext.Request.Headers.TryGetValue("accept", out stringvalues); if (stringvalues == "application/rdf+xml") { //Añadimos la etiquetqa ETag al header using (SHA256 sha256Hash = SHA256.Create()) { string etag = GetHash(sha256Hash, rdf); string ifNoneMatch = HttpContext.Request.Headers["If-None-Match"]; if (ifNoneMatch == etag) { HttpContext.Response.StatusCode = 304; } HttpContext.Response.Headers.Add("ETag", etag); } //Devolvemos en formato RDF return(File(Encoding.UTF8.GetBytes(rdf), "application/rdf+xml")); } else { RohRdfsReasoner reasoner = new RohRdfsReasoner(); reasoner.Initialise(ontologyGraph); RohGraph dataInferenceGraph = dataGraph.Clone(); reasoner.Apply(dataInferenceGraph); //Obtenemos datos del resto de grafos (para los provenance) Dictionary <string, List <Dictionary <string, SparqlObject.Data> > > sparqlObjectDictionaryGraphs = GetEntityDataGraphs(url); //Obtenemos las tablas configuradas List <Table> dataTables = GetDataTables(dataInferenceGraph, url); //Obtenemos los arborGrah configurados List <ArborGraph> dataArborGrahs = GetDataArborGraphs(dataInferenceGraph, dataGraph, url); //Obtenemos las 10 primeras entidades que apuntan a la entidad HashSet <string> inverseEntities = new HashSet <string>(); SparqlResultSet sparqlRdfType = (SparqlResultSet)dataInferenceGraph.ExecuteQuery("select distinct ?o where {<" + url + "> a ?o. }"); HashSet <string> rdfTypesEntity = new HashSet <string>(); foreach (SparqlResult sparqlResult in sparqlRdfType.Results) { rdfTypesEntity.Add(sparqlResult["o"].ToString()); } if (mLinked_Data_Server_Config.ExcludeRelatedEntity.Intersect(rdfTypesEntity).Count() == 0) { inverseEntities = GetInverseEntities(dataGraph, new HashSet <string>() { url }, new HashSet <string>(sparqlObjectDictionary.Keys), new Dictionary <string, SparqlObject>(), 10); } //Devolvemos en formato HTML List <String> allEntities = new List <string>(); SparqlResultSet sparqlResultSetEntidades = (SparqlResultSet)dataGraph.ExecuteQuery("select distinct ?p ?o where { ?s ?p ?o. FILTER (!isBlank(?o)) }"); foreach (SparqlResult sparqlResult in sparqlResultSetEntidades.Results) { if ((sparqlResult["o"] is UriNode) && (sparqlResult["p"].ToString() != "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")) { allEntities.Add(sparqlResult["o"].ToString()); } } //Preparamos el modelo de la entidad principal List <LinkedDataRdfViewModel> modelEntities = new List <LinkedDataRdfViewModel>(); LinkedDataRdfViewModel entidad = createLinkedDataRdfViewModel(url, dataGraph, sparqlObjectDictionaryGraphs, new List <string>(), allEntities, communNamePropierties, entitiesNames); modelEntities.Add(entidad); KeyValuePair <string, List <string> > titulo = entidad.stringPropertiesEntity.FirstOrDefault(x => mLinked_Data_Server_Config.PropsTitle.Contains(x.Key)); ViewData["Title"] = "About: " + url; if (titulo.Key != null) { ViewData["Title"] = "About: " + titulo.Value[0]; } ViewData["NameTitle"] = mConfigService.GetNameTitle(); //Preparamos el modelo del resto de entidades foreach (string entity in inverseEntities) { LinkedDataRdfViewModel entidadInversa = createLinkedDataRdfViewModel(entity, dataGraph, null, new List <string>(), allEntities, communNamePropierties, entitiesNames); modelEntities.Add(entidadInversa); } EntityModelTemplate entityModel = new EntityModelTemplate(); entityModel.linkedDataRDF = modelEntities; entityModel.propsTransform = mLinked_Data_Server_Config.PropsTransform; entityModel.tables = dataTables; entityModel.arborGraphs = dataArborGrahs; //Añadimos la etiquetqa ETag al header using (SHA256 sha256Hash = SHA256.Create()) { string stringToHash = JsonConvert.SerializeObject(entityModel.linkedDataRDF); stringToHash += JsonConvert.SerializeObject(entityModel.propsTransform); stringToHash += JsonConvert.SerializeObject(entityModel.tables); stringToHash += JsonConvert.SerializeObject(entityModel.arborGraphs); string etag = GetHash(sha256Hash, stringToHash); string ifNoneMatch = HttpContext.Request.Headers["If-None-Match"]; if (ifNoneMatch == etag) { HttpContext.Response.StatusCode = 304; } HttpContext.Response.Headers.Add("ETag", etag); } return(View(entityModel)); } } }
//TODO mover a otro sitio /// <summary> /// Realiza el proceso completo de desubrimiento sobre un RDF /// </summary> /// <param name="pDiscoverItem">Item de descubrimiento</param> /// <param name="pCallEtlApiService">Servicio para hacer llamadas a los métodos del controlador etl del API_CARGA </param> /// <param name="pCallUrisFactoryApiService">Servicio para hacer llamadas a los métodos del Uris Factory</param> /// <returns>DiscoverResult con los datos del descubrimiento</returns> private DiscoverResult Init(DiscoverItem pDiscoverItem, CallEtlApiService pCallEtlApiService, CallUrisFactoryApiService pCallUrisFactoryApiService) { #region Cargamos configuraciones ConfigSparql ConfigSparql = new ConfigSparql(); string SGI_SPARQLEndpoint = ConfigSparql.GetEndpoint(); string SGI_SPARQLGraph = ConfigSparql.GetGraph(); string SGI_SPARQLQueryParam = ConfigSparql.GetQueryParam(); string SGI_SPARQLUsername = ConfigSparql.GetUsername(); string SGI_SPARQLPassword = ConfigSparql.GetPassword(); string Unidata_SPARQLEndpoint = ConfigSparql.GetUnidataEndpoint(); string Unidata_SPARQLGraph = ConfigSparql.GetUnidataGraph(); string Unidata_SPARQLQueryParam = ConfigSparql.GetUnidataQueryParam(); string Unidata_SPARQLUsername = ConfigSparql.GetUnidataUsername(); string Unidata_SPARQLPassword = ConfigSparql.GetUnidataPassword(); ConfigService ConfigService = new ConfigService(); float MaxScore = ConfigService.GetMaxScore(); float MinScore = ConfigService.GetMinScore(); string UnidataDomain = ConfigService.GetUnidataDomain(); ConfigScopus ConfigScopus = new ConfigScopus(); string ScopusApiKey = ConfigScopus.GetScopusApiKey(); string ScopusUrl = ConfigScopus.GetScopusUrl(); ConfigCrossref ConfigCrossref = new ConfigCrossref(); string CrossrefUserAgent = ConfigCrossref.GetCrossrefUserAgent(); ConfigWOS ConfigWOS = new ConfigWOS(); string WOSAuthorization = ConfigWOS.GetWOSAuthorization(); #endregion DiscoverUtility discoverUtility = new DiscoverUtility(); DateTime discoverInitTime = DateTime.Now; //Cargamos la ontología if (_ontologyGraph == null) { _ontologyGraph = pCallEtlApiService.CallGetOntology(); } //Cargamos datos del RDF RohGraph dataGraph = new RohGraph(); Dictionary <string, HashSet <string> > discardDissambiguations = new Dictionary <string, HashSet <string> >(); if (!string.IsNullOrEmpty(pDiscoverItem.DiscoverRdf)) { //Si tenemos valor en DiscoverRdf, trabajamos con este RDF, ya que estamos reprocesando un rdf validado dataGraph.LoadFromString(pDiscoverItem.DiscoverRdf, new RdfXmlParser()); if (pDiscoverItem.DiscardDissambiguations != null) { foreach (DiscoverItem.DiscardDissambiguation discardDissambiguation in pDiscoverItem.DiscardDissambiguations) { if (!discardDissambiguations.ContainsKey(discardDissambiguation.IDOrigin)) { discardDissambiguations.Add(discardDissambiguation.IDOrigin, new HashSet <string>()); } discardDissambiguations[discardDissambiguation.IDOrigin].UnionWith(discardDissambiguation.DiscardCandidates); } } } else { dataGraph.LoadFromString(pDiscoverItem.Rdf, new RdfXmlParser()); } //Cargamos el razonador para inferir datos en la ontología RohRdfsReasoner reasoner = new RohRdfsReasoner(); reasoner.Initialise(_ontologyGraph); //Cargamos los datos con inferencia RohGraph dataInferenceGraph = dataGraph.Clone(); reasoner.Apply(dataInferenceGraph); //Datos para trabajar con la reconciliación ReconciliationData reconciliationData = new ReconciliationData(); //Datos para trabajar con el descubrimiento de enlaces DiscoverLinkData discoverLinkData = new DiscoverLinkData(); //Almacenamos las entidades con dudas acerca de su reonciliación Dictionary <string, Dictionary <string, float> > reconciliationEntitiesProbability = new Dictionary <string, Dictionary <string, float> >(); //Cargamos la caché global if (_discoverCacheGlobal == null) { _discoverCacheGlobal = new DiscoverCacheGlobal(); discoverUtility.LoadPersonWithName(_discoverCacheGlobal, SGI_SPARQLEndpoint, SGI_SPARQLGraph, SGI_SPARQLQueryParam, SGI_SPARQLUsername, SGI_SPARQLPassword); discoverUtility.LoadEntitiesWithTitle(_discoverCacheGlobal, SGI_SPARQLEndpoint, SGI_SPARQLGraph, SGI_SPARQLQueryParam, SGI_SPARQLUsername, SGI_SPARQLPassword); } if (!pDiscoverItem.DissambiguationProcessed) { bool hasChanges = true; //Cache del proceso de descubrimiento DiscoverCache discoverCache = new DiscoverCache(); //Se realizarán este proceso iterativamente hasta que no haya ningún cambio en lo que a reconciliaciones se refiere while (hasChanges) { hasChanges = false; //Preparamos los datos para proceder con la reconciliazción discoverUtility.PrepareData(dataGraph, reasoner, out dataInferenceGraph, out Dictionary <string, HashSet <string> > entitiesRdfTypes, out Dictionary <string, string> entitiesRdfType, out Dictionary <string, List <DisambiguationData> > disambiguationDataRdf, false); //Carga los scores de las personas //Aquí se almacenarán los nombres de las personas del RDF, junto con los candidatos de la BBDD y su score Dictionary <string, Dictionary <string, float> > namesScore = new Dictionary <string, Dictionary <string, float> >(); discoverUtility.LoadNamesScore(ref namesScore, dataInferenceGraph, discoverCache, _discoverCacheGlobal, MinScore, MaxScore); //0.- Macamos como reconciliadas aquellas que ya estén cargadas en la BBDD con los mismos identificadores List <string> entidadesCargadas = discoverUtility.LoadEntitiesDB(entitiesRdfType.Keys.ToList().Except(reconciliationData.reconciliatedEntityList.Keys.Union(reconciliationData.reconciliatedEntityList.Values)), SGI_SPARQLEndpoint, SGI_SPARQLGraph, SGI_SPARQLQueryParam, SGI_SPARQLUsername, SGI_SPARQLPassword).Keys.ToList(); foreach (string entitiID in entidadesCargadas) { reconciliationData.reconciliatedEntityList.Add(entitiID, entitiID); reconciliationData.reconciliatedEntitiesWithSubject.Add(entitiID); } //1.- Realizamos reconciliación con los identificadores configurados (y el roh:identifier) y marcamos como reconciliadas las entidades seleccionadas para no intentar reconciliarlas posteriormente discoverUtility.ReconciliateIDs(ref hasChanges, ref reconciliationData, entitiesRdfType, disambiguationDataRdf, discardDissambiguations, _ontologyGraph, ref dataGraph, discoverCache, SGI_SPARQLEndpoint, SGI_SPARQLQueryParam, SGI_SPARQLGraph, SGI_SPARQLUsername, SGI_SPARQLPassword); //2.- Realizamos la reconciliación con los datos del Propio RDF discoverUtility.ReconciliateRDF(ref hasChanges, ref reconciliationData, _ontologyGraph, ref dataGraph, reasoner, discardDissambiguations, discoverCache, _discoverCacheGlobal, MinScore, MaxScore); //3.- Realizamos la reconciliación con los datos de la BBDD discoverUtility.ReconciliateBBDD(ref hasChanges, ref reconciliationData, out reconciliationEntitiesProbability, _ontologyGraph, ref dataGraph, reasoner, namesScore, discardDissambiguations, discoverCache, _discoverCacheGlobal, MinScore, MaxScore, SGI_SPARQLEndpoint, SGI_SPARQLQueryParam, SGI_SPARQLGraph, SGI_SPARQLUsername, SGI_SPARQLPassword); //4.- Realizamos la reconciliación con los datos de las integraciones externas //TODO descomentar //discoverUtility.ExternalIntegration(ref hasChanges, ref reconciliationData, ref discoverLinkData, ref reconciliationEntitiesProbability, ref dataGraph, reasoner, namesScore,entitiesWithTitle, ontologyGraph, out Dictionary<string, ReconciliationData.ReconciliationScore> entidadesReconciliadasConIntegracionExternaAux, discardDissambiguations, discoverCache,discoverCacheGlobal, ScopusApiKey, ScopusUrl, CrossrefUserAgent, WOSAuthorization, MinScore, MaxScore, SGI_SPARQLEndpoint, SGI_SPARQLQueryParam, SGI_SPARQLGraph, SGI_SPARQLUsername, SGI_SPARQLPassword,pCallUrisFactoryApiService); //Eliminamos de las probabilidades aquellos que ya estén reconciliados foreach (string key in reconciliationData.reconciliatedEntityList.Keys) { reconciliationEntitiesProbability.Remove(key); } } //5.-Realizamos la detección de equivalencias con Unidata //TODO descomentar cuando esté habilitaado Unidata //TODO descomentar y revisar en unidata no tienen roh:identifier //discoverUtility.EquivalenceDiscover(ontologyGraph, ref dataGraph, reasoner, discoverCache, ref reconciliationEntitiesProbability, discardDissambiguations, UnidataDomain, MinScore, MaxScore, Unidata_SPARQLEndpoint, Unidata_SPARQLQueryParam, Unidata_SPARQLGraph, Unidata_SPARQLUsername, Unidata_SPARQLPassword); } //TODO comrpobar cuando esté habilitaado Unidata DateTime discoverEndTime = DateTime.Now; DiscoverResult resultado = new DiscoverResult(dataGraph, dataInferenceGraph, _ontologyGraph, reconciliationData, reconciliationEntitiesProbability, discoverInitTime, discoverEndTime, discoverLinkData); return(resultado); }
public IActionResult ResolveDiscover(string idJob, string IdDiscoverItem, Dictionary <string, string> DissambiguationProblemsResolve) { DiscoverItem item = _discoverItemService.GetDiscoverItemById(new Guid(IdDiscoverItem)); //Cargamos el RDF RohGraph dataGraph = new RohGraph(); dataGraph.LoadFromString(item.DiscoverRdf, new RdfXmlParser()); //Modificamos el RDF TripleStore store = new TripleStore(); store.Add(dataGraph); //Cambiamos candidato.Key por entityID foreach (string uriOriginal in DissambiguationProblemsResolve.Keys) { if (!string.IsNullOrEmpty(DissambiguationProblemsResolve[uriOriginal])) { //En caso de que la resolución sea una URI de Unidata añadimos el SameAs if (!string.IsNullOrEmpty(_unidataPrefix.GetUnidataDomain()) && DissambiguationProblemsResolve[uriOriginal].StartsWith(_unidataPrefix.GetUnidataDomain())) { IUriNode t_subject = dataGraph.CreateUriNode(UriFactory.Create(uriOriginal)); IUriNode t_predicate = dataGraph.CreateUriNode(UriFactory.Create("http://www.w3.org/2002/07/owl#sameAs")); IUriNode t_object = dataGraph.CreateUriNode(UriFactory.Create(DissambiguationProblemsResolve[uriOriginal])); dataGraph.Assert(new Triple(t_subject, t_predicate, t_object)); } else { //En caso de que la resolución NO sea una URI de Unidata modificamos las URLs SparqlUpdateParser parser = new SparqlUpdateParser(); //Actualizamos los sujetos SparqlUpdateCommandSet updateSubject = parser.ParseFromString(@"DELETE { ?s ?p ?o. } INSERT{<" + DissambiguationProblemsResolve[uriOriginal] + @"> ?p ?o.} WHERE { ?s ?p ?o. FILTER(?s = <" + uriOriginal + @">) }"); //Actualizamos los objetos SparqlUpdateCommandSet updateObject = parser.ParseFromString(@"DELETE { ?s ?p ?o. } INSERT{?s ?p <" + DissambiguationProblemsResolve[uriOriginal] + @">.} WHERE { ?s ?p ?o. FILTER(?o = <" + uriOriginal + @">) }"); LeviathanUpdateProcessor processor = new LeviathanUpdateProcessor(store); processor.ProcessCommandSet(updateSubject); processor.ProcessCommandSet(updateObject); } } } System.IO.StringWriter sw = new System.IO.StringWriter(); RdfXmlWriter rdfXmlWriter = new RdfXmlWriter(); rdfXmlWriter.Save(dataGraph, sw); string rdfXml = sw.ToString(); Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(rdfXml)); FormFile file = new FormFile(stream, 0, stream.Length, "rdfFile", "rdf.xml"); //Actualizamos el item Dictionary <string, List <string> > discards = new Dictionary <string, List <string> >(); foreach (DiscoverItem.DiscoverDissambiguation dissambiguation in item.DissambiguationProblems) { if (DissambiguationProblemsResolve.ContainsKey(dissambiguation.IDOrigin) && DissambiguationProblemsResolve[dissambiguation.IDOrigin] == null) { discards.Add(dissambiguation.IDOrigin, dissambiguation.DissambiguationCandiates.Select(x => x.IDCandidate).ToList()); } } item.UpdateDissambiguationDiscards(discards, rdfXml); item.DiscoverRdf = rdfXml; item.Status = "Pending"; _discoverItemService.ModifyDiscoverItem(item); //Lo reencolamos corregido junto con su identificador _callEDtlPublishService.CallDataPublish(file, idJob, false, IdDiscoverItem); return(RedirectToAction("DetailsJob", "Job", new { id = idJob })); }
/// <summary> /// Aplica el descubrimiento sobre las entidades cargadas en el SGI /// </summary> /// <param name="pSecondsSleep">Segundos para dormir después de procesar una entidad</param> /// <param name="pCallUrisFactoryApiService">Servicio para hacer llamadas a los métodos del Uris Factory</param> public void ApplyDiscoverLoadedEntities(int pSecondsSleep, CallUrisFactoryApiService pCallUrisFactoryApiService) { CallEtlApiService callEtlApiService = _serviceScopeFactory.CreateScope().ServiceProvider.GetRequiredService <CallEtlApiService>(); #region Cargamos configuraciones ConfigSparql ConfigSparql = new ConfigSparql(); string SGI_SPARQLEndpoint = ConfigSparql.GetEndpoint(); string SGI_SPARQLGraph = ConfigSparql.GetGraph(); string SGI_SPARQLQueryParam = ConfigSparql.GetQueryParam(); string SGI_SPARQLUsername = ConfigSparql.GetUsername(); string SGI_SPARQLPassword = ConfigSparql.GetPassword(); string Unidata_SPARQLEndpoint = ConfigSparql.GetUnidataEndpoint(); string Unidata_SPARQLGraph = ConfigSparql.GetUnidataGraph(); string Unidata_SPARQLQueryParam = ConfigSparql.GetUnidataQueryParam(); string Unidata_SPARQLUsername = ConfigSparql.GetUnidataUsername(); string Unidata_SPARQLPassword = ConfigSparql.GetUnidataPassword(); ConfigService ConfigService = new ConfigService(); string UnidataDomain = ConfigService.GetUnidataDomain(); string UnidataUriTransform = ConfigService.GetUnidataUriTransform(); float MaxScore = ConfigService.GetMaxScore(); float MinScore = ConfigService.GetMinScore(); ConfigScopus ConfigScopus = new ConfigScopus(); string ScopusApiKey = ConfigScopus.GetScopusApiKey(); string ScopusUrl = ConfigScopus.GetScopusUrl(); ConfigCrossref ConfigCrossref = new ConfigCrossref(); string CrossrefUserAgent = ConfigCrossref.GetCrossrefUserAgent(); ConfigWOS ConfigWOS = new ConfigWOS(); string WOSAuthorization = ConfigWOS.GetWOSAuthorization(); #endregion DiscoverUtility discoverUtility = new DiscoverUtility(); //Cargar todas las personas en la lista de manera aleatoria. List <string> personList = discoverUtility.GetPersonList(SGI_SPARQLEndpoint, SGI_SPARQLGraph, SGI_SPARQLQueryParam, SGI_SPARQLUsername, SGI_SPARQLPassword); List <string> randomPersonList = GetRandomOrderList(personList); RohGraph ontologyGraph = callEtlApiService.CallGetOntology(); foreach (string person in randomPersonList) { try { //Hora de inicio de la ejecución DateTime startTime = DateTime.Now; //Obtener el RohGraph de una única persona. RohGraph dataGraph = discoverUtility.GetDataGraphPersonLoadedForDiscover(person, SGI_SPARQLEndpoint, SGI_SPARQLGraph, SGI_SPARQLQueryParam, SGI_SPARQLUsername, SGI_SPARQLPassword); //Clonamos el grafo original para hacer luego comprobaciones RohGraph originalDataGraph = dataGraph.Clone(); RohRdfsReasoner reasoner = new RohRdfsReasoner(); reasoner.Initialise(ontologyGraph); RohGraph dataInferenceGraph = dataGraph.Clone(); reasoner.Apply(dataInferenceGraph); bool hasChanges = false; //Dictionary<string, string> discoveredEntityList = new Dictionary<string, string>(); Dictionary <string, Dictionary <string, float> > discoveredEntitiesProbability = new Dictionary <string, Dictionary <string, float> >(); Dictionary <string, ReconciliationData.ReconciliationScore> entidadesReconciliadasConIntegracionExternaAux; Dictionary <string, HashSet <string> > discardDissambiguations = new Dictionary <string, HashSet <string> >(); DiscoverCache discoverCache = new DiscoverCache(); DiscoverCacheGlobal discoverCacheGlobal = new DiscoverCacheGlobal(); //Obtención de la integración externa ReconciliationData reconciliationData = new ReconciliationData(); DiscoverLinkData discoverLinkData = new DiscoverLinkData(); Dictionary <string, List <DiscoverLinkData.PropertyData> > integration = discoverUtility.ExternalIntegration(ref hasChanges, ref reconciliationData, ref discoverLinkData, ref discoveredEntitiesProbability, ref dataGraph, reasoner, null, ontologyGraph, out entidadesReconciliadasConIntegracionExternaAux, discardDissambiguations, discoverCache, discoverCacheGlobal, ScopusApiKey, ScopusUrl, CrossrefUserAgent, WOSAuthorization, MinScore, MaxScore, SGI_SPARQLEndpoint, SGI_SPARQLGraph, SGI_SPARQLQueryParam, SGI_SPARQLUsername, SGI_SPARQLPassword, pCallUrisFactoryApiService, false); //Limpiamos 'integration' para no insertar triples en caso de que ya estén cargados foreach (string entity in integration.Keys.ToList()) { foreach (DiscoverLinkData.PropertyData propertyData in integration[entity].ToList()) { string p = propertyData.property; HashSet <string> objetos = new HashSet <string>(propertyData.valueProvenance.Keys.ToList()); foreach (string o in objetos) { if (((SparqlResultSet)originalDataGraph.ExecuteQuery($@"ASK WHERE {{ ?s ?p ?o. FILTER(?s=<{entity}>) FILTER(?p=<{p}>) FILTER(str(?o)='{o}') }}")).Result) { //Elimiamos el valor porque ya estaba cargado propertyData.valueProvenance.Remove(o); } } if (propertyData.valueProvenance.Count == 0) { integration[entity].Remove(propertyData); } } if (integration[entity].Count == 0) { integration.Remove(entity); } } //Creación de dataGraph con el contenido de 'integration' + RdfTypes + SameAS RohGraph dataGraphIntegration = new RohGraph(); foreach (string sujeto in integration.Keys) { IUriNode s = dataGraphIntegration.CreateUriNode(UriFactory.Create(sujeto)); //Agregamos SameAs y RDFType de las entidades SparqlResultSet sparqlResultSet = (SparqlResultSet)dataGraph.ExecuteQuery("select ?rdftype ?sameas where {?s a ?rdftype. OPTIONAL{?s <http://www.w3.org/2002/07/owl#sameAs> ?sameAS} FILTER(?s=<" + sujeto + ">)}"); foreach (SparqlResult sparqlResult in sparqlResultSet.Results) { string rdfType = sparqlResult["rdftype"].ToString(); IUriNode pRdfType = dataGraphIntegration.CreateUriNode(UriFactory.Create("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")); IUriNode oRdfType = dataGraphIntegration.CreateUriNode(UriFactory.Create(rdfType)); dataGraphIntegration.Assert(new Triple(s, pRdfType, oRdfType)); if (sparqlResult.Variables.Contains("sameas")) { string sameas = sparqlResult["sameas"].ToString(); IUriNode pSameAs = dataGraphIntegration.CreateUriNode(UriFactory.Create("http://www.w3.org/2002/07/owl#sameAs")); IUriNode oSameAs = dataGraphIntegration.CreateUriNode(UriFactory.Create(sameas)); dataGraphIntegration.Assert(new Triple(s, pSameAs, oSameAs)); } } foreach (DiscoverLinkData.PropertyData propertyData in integration[sujeto]) { foreach (string valor in propertyData.valueProvenance.Keys) { IUriNode p = dataGraphIntegration.CreateUriNode(UriFactory.Create(propertyData.property)); if (Uri.IsWellFormedUriString(valor, UriKind.Absolute)) { IUriNode uriNode = dataGraphIntegration.CreateUriNode(UriFactory.Create(propertyData.property)); dataGraphIntegration.Assert(new Triple(s, p, uriNode)); } else { ILiteralNode literalNode = dataGraphIntegration.CreateLiteralNode(valor, new Uri("http://www.w3.org/2001/XMLSchema#string")); dataGraphIntegration.Assert(new Triple(s, p, literalNode)); } foreach (string org in propertyData.valueProvenance[valor]) { //Agregamos los datos de las organizaciones y los grafos SparqlResultSet sparqlResultSetOrgs = (SparqlResultSet)dataGraph.ExecuteQuery("select ?s ?p ?o where {?s ?p ?o. FILTER(?s in(<" + pCallUrisFactoryApiService.GetUri("http://purl.org/roh/mirror/foaf#Organization", org) + ">,<" + pCallUrisFactoryApiService.GetUri("Graph", org) + "> ))}"); foreach (SparqlResult sparqlResult in sparqlResultSetOrgs.Results) { INode sOrg = dataGraphIntegration.CreateUriNode(UriFactory.Create(sparqlResult["s"].ToString())); INode pOrg = dataGraphIntegration.CreateUriNode(UriFactory.Create(sparqlResult["p"].ToString())); if (sparqlResult["o"] is UriNode) { INode oOrg = dataGraphIntegration.CreateUriNode(UriFactory.Create(sparqlResult["o"].ToString())); dataGraphIntegration.Assert(new Triple(sOrg, pOrg, oOrg)); } else if (sparqlResult["o"] is LiteralNode) { INode oOrg = dataGraphIntegration.CreateLiteralNode(((LiteralNode)sparqlResult["o"]).Value, ((LiteralNode)sparqlResult["o"]).DataType); dataGraphIntegration.Assert(new Triple(sOrg, pOrg, oOrg)); } } } } } } //Hora fin de la ejecución DateTime endTime = DateTime.Now; if (integration.Count > 0) { //Si hay datos nuevos los cargamos string urlDiscoverAgent = pCallUrisFactoryApiService.GetUri("Agent", "discover"); //Publicamos en el SGI AsioPublication asioPublication = new AsioPublication(SGI_SPARQLEndpoint, SGI_SPARQLQueryParam, SGI_SPARQLGraph, SGI_SPARQLUsername, SGI_SPARQLPassword); asioPublication.PublishRDF(dataGraphIntegration, null, new KeyValuePair <string, string>(urlDiscoverAgent, "Algoritmos de descubrimiento"), startTime, endTime, discoverLinkData, pCallUrisFactoryApiService); //Preparamos los datos para cargarlos en Unidata RohGraph unidataGraph = dataGraphIntegration.Clone(); #region Si no tiene un sameAs apuntando a Unidata lo eliminamos, no hay que cargar la entidad SparqlResultSet sparqlResultSet = (SparqlResultSet)unidataGraph.ExecuteQuery("select ?s ?rdftype ?sameas where {?s a ?rdftype. OPTIONAL{?s <http://www.w3.org/2002/07/owl#sameAs> ?sameAS} }"); Dictionary <string, bool> entidadesConSameAsUnidata = new Dictionary <string, bool>(); foreach (SparqlResult sparqlResult in sparqlResultSet.Results) { string s = sparqlResult["s"].ToString(); if (!entidadesConSameAsUnidata.ContainsKey(s)) { entidadesConSameAsUnidata.Add(s, false); } if (sparqlResult.Variables.Contains("sameas")) { if (sparqlResult["sameas"].ToString().StartsWith(UnidataDomain)) { entidadesConSameAsUnidata[s] = true; } } } TripleStore store = new TripleStore(); store.Add(unidataGraph); foreach (string entity in entidadesConSameAsUnidata.Keys) { if (!entidadesConSameAsUnidata[entity]) { //Cambiamos candidato.Key por entityID SparqlUpdateParser parser = new SparqlUpdateParser(); SparqlUpdateCommandSet delete = parser.ParseFromString(@"DELETE { ?s ?p ?o. } WHERE { ?s ?p ?o. FILTER(?s = <" + entity + @">) }"); LeviathanUpdateProcessor processor = new LeviathanUpdateProcessor(store); processor.ProcessCommandSet(delete); } } #endregion //TODO descomentar cuando esté habilitaado Unidata ////Si hay triples para cargar en Unidata procedemos //if (unidataGraph.Triples.ToList().Count > 0) //{ // //Publicamos en UNIDATA // AsioPublication asioPublicationUnidata = new AsioPublication(Unidata_SPARQLEndpoint, Unidata_SPARQLQueryParam, Unidata_SPARQLGraph, Unidata_SPARQLUsername, Unidata_SPARQLPassword); // // Prepara el grafo para su carga en Unidata, para ello coge las URIs de Unidata del SameAs y la aplica a los sujetos y los antiguos sujetos se agregan al SameAs // unidataGraph = AsioPublication.TransformUrisToUnidata(unidataGraph, UnidataDomain, UnidataUriTransform); // asioPublicationUnidata.PublishRDF(unidataGraph, null, new KeyValuePair<string, string>(urlDiscoverAgent, "Algoritmos de descubrimiento"), startTime, endTime, discoverLinkData,pCallUrisFactoryApiService); //} } } catch (Exception exception) { Logging.Error(exception); } Thread.Sleep(pSecondsSleep * 1000); } }