001package conexp.fx.core.importer; 002 003/* 004 * #%L 005 * Concept Explorer FX 006 * %% 007 * Copyright (C) 2010 - 2019 Francesco Kriegel 008 * %% 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as 011 * published by the Free Software Foundation, either version 3 of the 012 * License, or (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public 020 * License along with this program. If not, see 021 * <http://www.gnu.org/licenses/gpl-3.0.html>. 022 * #L% 023 */ 024 025import java.io.File; 026import java.io.IOException; 027import java.io.InputStream; 028import java.net.URL; 029import java.net.URLEncoder; 030import java.nio.file.Files; 031import java.util.ArrayList; 032import java.util.HashSet; 033import java.util.List; 034import java.util.Set; 035import java.util.stream.Collectors; 036 037import org.openrdf.model.Statement; 038import org.openrdf.model.ValueFactory; 039import org.openrdf.model.impl.StatementImpl; 040import org.openrdf.model.impl.ValueFactoryImpl; 041import org.openrdf.model.vocabulary.RDF; 042import org.openrdf.query.BindingSet; 043import org.openrdf.query.MalformedQueryException; 044import org.openrdf.query.QueryEvaluationException; 045import org.openrdf.query.QueryLanguage; 046import org.openrdf.query.QueryResultHandlerException; 047import org.openrdf.query.TupleQueryResultHandler; 048import org.openrdf.query.TupleQueryResultHandlerException; 049import org.openrdf.query.resultio.QueryResultParseException; 050import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLParser; 051import org.openrdf.repository.Repository; 052import org.openrdf.repository.RepositoryConnection; 053import org.openrdf.repository.RepositoryException; 054import org.openrdf.repository.sail.SailRepository; 055import org.openrdf.rio.RDFFormat; 056import org.openrdf.rio.RDFParseException; 057import org.openrdf.sail.memory.MemoryStore; 058import org.semanticweb.owlapi.model.IRI; 059 060import conexp.fx.core.collections.Pair; 061import conexp.fx.core.collections.setlist.HashSetArrayList; 062import conexp.fx.core.collections.setlist.SetList; 063import conexp.fx.core.context.MatrixContext; 064import conexp.fx.core.dl.Signature; 065import conexp.fx.core.dl.deprecated.OWLInterpretation; 066 067public class RDFImporter { 068 069 public static final void readCSV(final Repository repository, final File file) 070 throws RepositoryException, RDFParseException, IOException { 071 final RepositoryConnection connection = repository.getConnection(); 072 final ValueFactory f = new ValueFactoryImpl(); 073 Files 074 .lines(file.toPath()) 075 .map(line -> line.split(";")) 076 .map( 077 tuple -> new StatementImpl( 078 f.createURI(file.getName() + ":", tuple[0]), 079 f.createURI(file.getName() + ":", tuple[1]), 080 f.createURI(file.getName() + ":", tuple[2]))) 081 .forEach(statement -> { 082 try { 083 connection.add(statement); 084 } catch (RepositoryException e) { 085 throw new RuntimeException(e); 086 } 087 }); 088 connection.commit(); 089 connection.close(); 090 } 091 092 public static final Repository read(final File file) throws RepositoryException, RDFParseException, IOException { 093 final Repository repository = new SailRepository(new MemoryStore()); 094 read(repository, file); 095 return repository; 096 } 097 098 public static final void read(final Repository repository, final File file) 099 throws RepositoryException, RDFParseException, IOException { 100 final RepositoryConnection connection = repository.getConnection(); 101 connection.add(file, null, RDFFormat.forFileName(file.getName(), RDFFormat.RDFXML)); 102 connection.commit(); 103 connection.close(); 104 } 105 106 public static final Repository read(final URL url) throws RepositoryException, RDFParseException, IOException { 107 final Repository repository = new SailRepository(new MemoryStore()); 108 read(repository, url); 109 return repository; 110 } 111 112 public static final void read(final Repository repository, final URL url) 113 throws RepositoryException, RDFParseException, IOException { 114 final RepositoryConnection connection = repository.getConnection(); 115 connection.add(url, null, RDFFormat.forFileName(url.toString(), RDFFormat.RDFXML)); 116 connection.commit(); 117 connection.close(); 118 } 119 120 private static final class ContextTupleQueryResultHandler implements TupleQueryResultHandler { 121 122 private final MatrixContext<String, String> context; 123 private boolean objectTuples = true; 124 private boolean attributeTuples = true; 125 private final List<String> objectBindingNames = new ArrayList<String>(); 126 private final List<String> attributeBindingNames = new ArrayList<String>(); 127 private final SetList<String> objects = new HashSetArrayList<String>(); 128 private final SetList<String> attributes = new HashSetArrayList<String>(); 129 private final Set<Pair<String, String>> crosses = new HashSet<Pair<String, String>>(); 130 131 private ContextTupleQueryResultHandler(final MatrixContext<String, String> context) { 132 this.context = context; 133// context.lock(); 134 context.rowHeads().add("null"); 135 context.colHeads().add("null"); 136 } 137 138 public void handleBoolean(final boolean value) throws QueryResultHandlerException { 139 System.out.println("handle boolean " + value); 140 } 141 142 public void handleLinks(final List<String> linkUrls) throws QueryResultHandlerException { 143 System.out.println("handle links " + linkUrls); 144 } 145 146 public final void startQueryResult(final List<String> bindingNames) throws TupleQueryResultHandlerException { 147 for (String bindingName : bindingNames) 148 if (bindingName.toLowerCase().startsWith("object")) 149 objectBindingNames.add(bindingName); 150 else if (bindingName.toLowerCase().startsWith("attribute")) 151 attributeBindingNames.add(bindingName); 152 if (objectBindingNames.size() == 1) 153 objectTuples = false; 154 if (attributeBindingNames.size() == 1) 155 attributeTuples = false; 156 } 157 158 public final void endQueryResult() throws TupleQueryResultHandlerException { 159 System.out.println("adding " + objects.size() + " objects"); 160 context.rowHeads().addAll(0, objects); 161 System.out.println("adding " + attributes.size() + " attributes"); 162 context.colHeads().addAll(0, attributes); 163 context.rowHeads().remove("null"); 164 context.colHeads().remove("null"); 165 System.out.println("adding " + crosses.size() + " crosses"); 166 for (Pair<String, String> p : crosses) 167 context.addFastSilent(p.x(), p.y()); 168 // context.unlock(); 169 context.pushAllChangedEvent(); 170 } 171 172 public final void handleSolution(final BindingSet bindingSet) throws TupleQueryResultHandlerException { 173 String object = "", attribute = ""; 174 if (objectTuples) { 175 for (String objectBindingName : objectBindingNames) 176 object += bindingSet.getBinding(objectBindingName).getValue().stringValue() + "; "; 177 object = object.substring(0, object.length() - 2); 178 } else 179 object = bindingSet.getBinding(objectBindingNames.get(0)).getValue().stringValue(); 180 if (attributeTuples) { 181 for (String attributeBindingName : attributeBindingNames) 182 attribute += bindingSet.getBinding(attributeBindingName).getValue().stringValue() + "; "; 183 attribute = attribute.substring(0, attribute.length() - 2); 184 } else 185 attribute = bindingSet.getBinding(attributeBindingNames.get(0)).getValue().stringValue(); 186 objects.add(object); 187 attributes.add(attribute); 188 crosses.add(Pair.of(object, attribute)); 189 } 190 } 191 192 public static void importXML(final MatrixContext<String, String> context, String url, String query) { 193 try { 194 final SPARQLResultsXMLParser parser = new SPARQLResultsXMLParser(); 195 parser.setTupleQueryResultHandler(new ContextTupleQueryResultHandler(context)); 196 final String queryURL = new String(url).replace("<QUERY>", URLEncoder.encode(query, "UTF-8")); 197 System.out.println("reading " + queryURL); 198 final InputStream stream = new URL(queryURL).openStream(); 199 System.out.println("parsing results"); 200 parser.parseQueryResult(stream); 201 System.out.println("parse done"); 202 } catch (QueryResultParseException | QueryResultHandlerException | IOException e) { 203 e.printStackTrace(); 204 } 205 } 206 207 public static void importRepository(MatrixContext<String, String> context, Repository repo, String query) { 208 try { 209 final RepositoryConnection connection = repo.getConnection(); 210 connection.prepareTupleQuery(QueryLanguage.SPARQL, query).evaluate(new ContextTupleQueryResultHandler(context)); 211 connection.close(); 212 } catch (QueryEvaluationException | RepositoryException | MalformedQueryException 213 | TupleQueryResultHandlerException e) { 214 e.printStackTrace(); 215 } 216 } 217 218 public static void importFile(MatrixContext<String, String> context, File file, String query) { 219 try { 220 importRepository(context, read(file), query); 221 } catch (RepositoryException | RDFParseException | IOException e) { 222 e.printStackTrace(); 223 } 224 } 225 226 public static void importURL(MatrixContext<String, String> context, String url, String query) { 227 try { 228 importRepository(context, read(new URL(url)), query); 229 } catch (RepositoryException | RDFParseException | IOException e) { 230 e.printStackTrace(); 231 } 232 } 233 234 public static final OWLInterpretation extractInterpretation(final List<Statement> triples) { 235 return extractInterpretation(triples, IRI.create(RDF.TYPE.stringValue())); 236 } 237 238 public static final OWLInterpretation 239 extractInterpretation(final List<Statement> triples, final IRI selectedIsARoleName) { 240 final List<IRI> roleNames = 241 triples.parallelStream().map(triple -> IRI.create(triple.getPredicate().stringValue())).distinct().collect( 242 Collectors.toList()); 243 if (!roleNames.contains(selectedIsARoleName)) 244 throw new IllegalArgumentException(); 245 roleNames.remove(selectedIsARoleName); 246 final List<IRI> conceptNames = triples 247 .parallelStream() 248 .filter(triple -> IRI.create(triple.getPredicate().stringValue()).equals(selectedIsARoleName)) 249 .map(triple -> IRI.create(triple.getObject().stringValue())) 250 .collect(Collectors.toList()); 251 return extractInterpretation(triples, conceptNames, roleNames, selectedIsARoleName); 252 } 253 254 public static final OWLInterpretation extractInterpretation( 255 final List<Statement> triples, 256 final List<IRI> selectedConceptNames, 257 final List<IRI> selectedRoleNames, 258 final IRI selectedIsARoleName) { 259 final Signature signature = new Signature(null); 260 signature.getConceptNames().addAll(selectedConceptNames); 261 signature.getRoleNames().addAll(selectedRoleNames); 262 signature.getIndividualNames().addAll( 263 triples 264 .parallelStream() 265 .filter( 266 triple -> IRI.create(triple.getPredicate().stringValue()).equals(selectedIsARoleName) 267 && signature.getConceptNames().contains(IRI.create(triple.getObject().stringValue()))) 268 .map(triple -> IRI.create(triple.getSubject().stringValue())) 269 .collect(Collectors.toSet())); 270 final OWLInterpretation i = new OWLInterpretation(signature); 271 triples.stream().forEach(triple -> { 272 if (IRI.create(triple.getPredicate().stringValue()).equals(selectedIsARoleName)) { 273 if (signature.getConceptNames().contains(IRI.create(triple.getObject().stringValue())) 274 && signature.getIndividualNames().contains(IRI.create(triple.getSubject().stringValue()))) { 275 i.addConceptNameAssertion( 276 IRI.create(triple.getObject().stringValue()), 277 IRI.create(triple.getSubject().stringValue())); 278 } 279 } else if (signature.getRoleNames().contains(IRI.create(triple.getPredicate().stringValue())) 280 && signature.getIndividualNames().contains(IRI.create(triple.getSubject().stringValue())) 281 && signature.getIndividualNames().contains(IRI.create(triple.getObject().stringValue()))) { 282 i.addRoleNameAssertion( 283 IRI.create(triple.getPredicate().stringValue()), 284 IRI.create(triple.getSubject().stringValue()), 285 IRI.create(triple.getObject().stringValue())); 286 } 287 }); 288 return i; 289 } 290 291}