package won.matcher.service.nodemanager.service;

import org.apache.jena.query.*;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import won.matcher.service.common.service.sparql.SparqlService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import won.protocol.exception.DataIntegrityException;
import won.protocol.service.WonNodeInfo;
import won.protocol.util.WonRdfUtils;
import won.protocol.vocabulary.WON;

import java.net.URI;
import java.util.HashSet;
import java.util.Set;

/**
 * Sparql service extended with methods for won node controller
 *
 * User: hfriedrich
 * Date: 04.05.2015
 */
@Component
public class WonNodeSparqlService extends SparqlService
{

  @Autowired
  public WonNodeSparqlService(@Value("${uri.sparql.endpoint}") final String sparqlEndpoint) {
    super(sparqlEndpoint);
  }

  /**
   * Retrieve resource data of all known won nodes that are saved in the Sparql endpoint.
   *
   * @return Set of all known won node resource data
   */
  public Set<WonNodeInfo> retrieveAllWonNodeInfo() {

    Set<WonNodeInfo> wonNodeInfos = new HashSet<>();
    String queryString = "SELECT ?graphUri ?nodeUri WHERE { GRAPH ?graphUri {?nodeUri <%s> ?c} }";
    queryString = String.format(queryString, WON.HAS_URI_PATTERN_SPECIFICATION.toString());
    log.debug("Query SPARQL Endpoint: {}", sparqlEndpoint);
    log.debug("Execute query: {}", queryString);
    Query query = QueryFactory.create(queryString);
    QueryExecution qexec = QueryExecutionFactory.sparqlService(sparqlEndpoint, query);
    ResultSet results = qexec.execSelect();

    while (results.hasNext()) {

      QuerySolution qs = results.nextSolution();
      RDFNode rdfNode = qs.get("graphUri");
      if (rdfNode != null) {
        String graphUri = rdfNode.asResource().getURI();
        Dataset ds = retrieveDataset(graphUri);
        WonNodeInfo nodeInfo = getWonNodeInfoFromDataset(ds);
        wonNodeInfos.add(nodeInfo);
      }
    }
    qexec.close();
    return wonNodeInfos;
  }

  /**
   * Get the {@link won.protocol.service.WonNodeInfo} as an object from a {@link Dataset}
   *
   * @param ds Dataset which holds won node information
   * @return
   */
  public WonNodeInfo getWonNodeInfoFromDataset(Dataset ds) {

    String dsWonNodeUri = getWonNodeUriFromDataset(ds);
    WonNodeInfo nodeInfo = WonRdfUtils.WonNodeUtils.getWonNodeInfo(URI.create(dsWonNodeUri), ds);
    if (nodeInfo == null) {
      throw new DataIntegrityException(
        "Could not load won node info from dataset with URI: " + dsWonNodeUri);
    }

    return nodeInfo;
  }

  /**
   * Get the won node URI from a {@link Dataset}
   *
   * @param ds Dataset which holds won node information
   * @return
   */
  private String getWonNodeUriFromDataset(Dataset ds) {

    if (ds.listNames().hasNext()) {
      Model model = ds.getNamedModel(ds.listNames().next());
      if (model.listSubjectsWithProperty(WON.HAS_URI_PATTERN_SPECIFICATION).hasNext()) {
        return model.listSubjectsWithProperty(WON.HAS_URI_PATTERN_SPECIFICATION).nextResource().toString();
      }
    }
    return null;
  }

}

@@ -1313,113 +1313,218 @@
 Uri 
-%3C%25s%3E ?c%7D %7D%22;%0A    queryString = String.format(queryString, WON.HAS_URI_PATTERN_SPECIFICATION.toString()
+won:hasUriPrefixSpecification ?c%7D %7D%22;%0A    ParameterizedSparqlString pps = new ParameterizedSparqlString();%0A    pps.setCommandText(queryString);%0A    pps.setNsPrefix(%22won%22, %22http://purl.org/webofneeds/model#%22
 );%0A
+%0A
     
@@ -1618,71 +1618,22 @@
 %7D%22, 
-queryString);%0A    Query query = QueryFactory.create(query
+pps.to
 String
+()
 );%0A 
@@ -1710,21 +1710,29 @@
 dpoint, 
-q
+pps.asQ
 uery
+()
 );%0A    R

use ParameterizedSparqlString in WonNodeSparqlService to create queries more safely