package es.upm.fi.dia.oeg.map4rdf.server.command; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import net.customware.gwt.dispatch.server.ActionHandler; import net.customware.gwt.dispatch.server.ExecutionContext; import net.customware.gwt.dispatch.shared.ActionException; import com.google.inject.Inject; import com.hp.hpl.jena.query.QueryExecution; import com.hp.hpl.jena.query.QueryExecutionFactory; import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.ResultSet; import es.upm.fi.dia.oeg.map4rdf.client.action.GetViajeroResource; import es.upm.fi.dia.oeg.map4rdf.client.action.SingletonResult; import es.upm.fi.dia.oeg.map4rdf.server.conf.multiple.MultipleConfigurations; import es.upm.fi.dia.oeg.map4rdf.share.conf.ParameterNames; import es.upm.fi.dia.oeg.map4rdf.share.viajero.TripProvenance; import es.upm.fi.dia.oeg.map4rdf.share.viajero.ViajeroGuide; import es.upm.fi.dia.oeg.map4rdf.share.viajero.ViajeroImage; import es.upm.fi.dia.oeg.map4rdf.share.viajero.ViajeroResourceContainer; import es.upm.fi.dia.oeg.map4rdf.share.viajero.ViajeroTrip; import es.upm.fi.dia.oeg.map4rdf.share.viajero.TripProvenance.TripProvenanceType; /** * @author Daniel Garijo Adapted by: @author Francisco Siles */ public class GetViajeroResourceHandler implements ActionHandler<GetViajeroResource, SingletonResult<ViajeroResourceContainer>> { private MultipleConfigurations configurations; private Logger logger = Logger.getLogger(GetViajeroResourceHandler.class); @Inject public GetViajeroResourceHandler(MultipleConfigurations configurations) { this.configurations = configurations; } @Override public SingletonResult<ViajeroResourceContainer> execute( GetViajeroResource action, ExecutionContext context) throws ActionException { String uri = action.getUri(); if (uri == null || uri.length() == 0) { throw new ActionException("Invalid URI: " + uri); } if(!configurations.existsConfiguration(action.getConfigID())){ throw new ActionException("Bad Config ID"); } String endpointUri=configurations.getConfiguration(action.getConfigID()) .getConfigurationParamValue(ParameterNames.ENDPOINT_URL); if(endpointUri==null || endpointUri.isEmpty()){ throw new ActionException("Bad endpoint URL in config file"); } ViajeroResourceContainer resource = getDatosGuiasViajes(endpointUri,uri); return new SingletonResult<ViajeroResourceContainer>(resource); } @Override public Class<GetViajeroResource> getActionType() { return GetViajeroResource.class; } @Override public void rollback(GetViajeroResource action, SingletonResult<ViajeroResourceContainer> result, ExecutionContext context) throws ActionException { // nothing to do } private ViajeroResourceContainer getDatosGuiasViajes(String endpointUri,String uri) { ViajeroResourceContainer resource = new ViajeroResourceContainer(); List<ViajeroGuide> guides = getGuides(endpointUri,100, uri); if (guides != null && !guides.isEmpty()) { resource.addAllGuides(guides); } List<ViajeroTrip> trips = getTrips(endpointUri,100, uri); if (trips != null && !trips.isEmpty()) { resource.addAllTrips(trips); } return resource; } private List<ViajeroGuide> getGuides(String endpointUri, int i, String uri) { /* * TODO modify this method, wait for Ocorcho to change the model. The * images are property in endpoint. The application does not need to get * redirected urls and does not need to check urls. */ Map<String, ViajeroGuide> guides = new HashMap<String, ViajeroGuide>(); long start = Calendar.getInstance().getTimeInMillis(); QueryExecution exec = QueryExecutionFactory.sparqlService(endpointUri, createGetGuidesQuery(100, uri)); ResultSet queryResult = exec.execSelect(); long medium1 = Calendar.getInstance().getTimeInMillis(); long checkURI = 0; long checkImage = 0; int imagenes = 0; while (queryResult.hasNext()) { // guia String uriGuide = "", urlGuide = "", titleGuide = "", dateGuia = ""; QuerySolution solution = queryResult.next(); if (solution.contains("noticia")) { uriGuide = solution.getResource("noticia").getURI(); } else { uriGuide = ""; } if (solution.contains("title")) { titleGuide = solution.getLiteral("title").getLexicalForm(); } else { titleGuide = ""; } if (solution.contains("url")) { urlGuide = solution.getLiteral("url").getLexicalForm(); } else { urlGuide = ""; } if (solution.contains("dateG")) { dateGuia = solution.getLiteral("dateG").getLexicalForm(); } else { dateGuia = ""; } long tempCheckURIStart = Calendar.getInstance().getTimeInMillis(); if (!uriGuide.equals("") && !uriGuide.isEmpty() && !urlGuide.equals("") && !urlGuide.isEmpty() && checkIfURLExists(urlGuide)) { long tempCheckURIStop = Calendar.getInstance() .getTimeInMillis(); checkURI += tempCheckURIStop - tempCheckURIStart; ViajeroGuide g; if (guides.containsKey(uriGuide) && guides.get(uriGuide) != null) { g = guides.get(uriGuide); } else { g = new ViajeroGuide(titleGuide, urlGuide, uriGuide, dateGuia); guides.put(uriGuide, g); } ViajeroImage image = null; if (solution.contains("uriImage") && solution.contains("pnameImage")) { String uriImage = solution.getResource("uriImage").getURI(); String pnameImage = solution.getLiteral("pnameImage") .getLexicalForm(); long tempCheckImageStart = Calendar.getInstance() .getTimeInMillis(); String imageURL = getImageURL(urlGuide, g.getImages() .size()); long tempCheckImageStop = Calendar.getInstance() .getTimeInMillis(); checkImage += tempCheckImageStop - tempCheckImageStart; if (!imageURL.equals("") && !imageURL.isEmpty()) { if (solution.contains("titImage")) { String titImage = solution.getLiteral("titImage") .getLexicalForm(); image = new ViajeroImage(uriImage, getNewPname(pnameImage), imageURL, titImage); imagenes++; } else { image = new ViajeroImage(uriImage, getNewPname(pnameImage), imageURL); imagenes++; } } } if (image != null) { g.addImage(image); } } } long end = Calendar.getInstance().getTimeInMillis(); int recursosSinImagenes = 0; int imagenesDeMas = 0; for (ViajeroGuide guide : guides.values()) { if (guide.getImages().isEmpty()) { recursosSinImagenes++; } else if (guide.getImages().size() > 1) { imagenesDeMas += guide.getImages().size() - 1; } } /* * System.out.println( * "-----------------------------------------------------"); * System.out.println("Punto:"+uri); * System.out.println("Recursos obtenidos:"+guides.values().size()); * System.out.println("Imagenes obtenidas:"+imagenes); * System.out.println("Recursos sin imagenes:"+recursosSinImagenes); * System.out.println("Imagenes de mas en recursos:"+imagenesDeMas); * System.out.println("Tiempo ejecutar select:"+(medium1-start)); * System. * out.println("Tiempo en conseguir todos los datos:"+(end-medium1)); * System.out.println("Tiempo en checkear URIs:"+checkURI); * System.out.println("Tiempo en obtener las imagenes:"+checkImage); * System.out.println("Tiempo total:"+(end-start)); System.out.println( * "-----------------------------------------------------"); */ return new ArrayList<ViajeroGuide>(guides.values()); } private List<ViajeroTrip> getTrips(String endpointUri, int i, String uri) { // viaje QueryExecution exec = QueryExecutionFactory.sparqlService(endpointUri, createGetTripsQuery(i, uri)); Map<String, ViajeroTrip> tripsMaps = new HashMap<String, ViajeroTrip>(); ResultSet queryResult = exec.execSelect(); while (queryResult.hasNext()) { QuerySolution solution = queryResult.next(); String uriTrip = "", titTrip = "", tripURL = "", dateViaje = ""; if (solution.contains("trip")) { uriTrip = solution.getResource("trip").getURI(); } else { uriTrip = ""; } if (solution.contains("tripTitle")) { titTrip = solution.getLiteral("tripTitle").getLexicalForm(); } else { titTrip = ""; } if (solution.contains("tripURL")) { tripURL = solution.getLiteral("tripURL").getLexicalForm(); } else { tripURL = ""; } if (solution.contains("created")) { dateViaje = solution.getLiteral("created").getLexicalForm(); } else { dateViaje = ""; } if (!uriTrip.equals("")) { ViajeroTrip t = new ViajeroTrip(titTrip, tripURL, uriTrip, uri, dateViaje); addOtherTripsVariables(t, solution); if (!tripsMaps.containsKey(uriTrip)) { tripsMaps.put(uriTrip, t); addProvenanceTrip(endpointUri,uriTrip, t); } } } return new ArrayList<ViajeroTrip>(tripsMaps.values()); } private void addOtherTripsVariables(ViajeroTrip trip, QuerySolution solution) { // ADD ?pL ?pH ?dL ?dH ?tD ?prL ?prH // pL = price less than // pH = price more than // dL = duration less than // dH = duration more than // tD = description // prL = distance less km than // prh = dsitance more km than if (solution.contains("pL")) { trip.setPriceLess((solution.getLiteral("pL").getLexicalForm())); } if (solution.contains("pH")) { trip.setPriceMore((solution.getLiteral("pH").getLexicalForm())); } if (solution.contains("dL")) { trip.setDurationLess((solution.getLiteral("dL").getLexicalForm())); } if (solution.contains("dH")) { trip.setDurationMore((solution.getLiteral("dH").getLexicalForm())); } if (solution.contains("tD")) { trip.setDescription((solution.getLiteral("tD").getLexicalForm())); } if (solution.contains("prL")) { trip.setDistanceLess((solution.getLiteral("prL").getLexicalForm())); } if (solution.contains("prH")) { trip.setDistanceMore((solution.getLiteral("prH").getLexicalForm())); } } private void addProvenanceTrip(String endpointUri,String uriTrip, ViajeroTrip trip){ QueryExecution exec2 = QueryExecutionFactory.sparqlService(endpointUri, createGetTripProvenance(1000, uriTrip)); ResultSet queryResult2 = exec2.execSelect(); String nextV = ""; while (queryResult2.hasNext()) { QuerySolution solution2 = queryResult2.next(); if (solution2.contains("nextV")) { nextV = solution2.getResource("nextV").getURI(); } TripProvenance provenance = createTripProvenance(solution2,trip.getDate()); if(provenance!=null){ trip.addTripProvenance(provenance); } } int maxProvenances=100; while (!nextV.trim().isEmpty() && maxProvenances>0) { exec2 = QueryExecutionFactory.sparqlService(endpointUri, createGetTripProvenance(1000, nextV)); maxProvenances--; queryResult2 = exec2.execSelect(); nextV = ""; while (queryResult2.hasNext()) { QuerySolution solution2 = queryResult2.next(); if (solution2.contains("nextV")) { nextV = solution2.getResource("nextV").getURI(); } TripProvenance provenance = createTripProvenance(solution2,trip.getDate()); if(provenance!=null){ trip.addTripProvenance(provenance); } } } } private TripProvenance createTripProvenance(QuerySolution qs,String refTime) { String reference = "", time = ""; reference = qs.getResource("reference").getURI(); if (qs.contains("time")) { time = qs.getLiteral("time").getLexicalForm(); } else { time = refTime; } TripProvenanceType provenanceType=TripProvenanceType.GUIDE; if (reference.contains("/Post/")) { provenanceType=TripProvenanceType.POST; } else if (reference.contains("/Image/")){ provenanceType=TripProvenanceType.IMAGE; } else if (reference.contains("/Video/")) { provenanceType=TripProvenanceType.VIDEO; }else if (reference.contains("/Guide/")) { provenanceType=TripProvenanceType.GUIDE; }else{ return null; } TripProvenance provenance= new TripProvenance(reference,provenanceType); provenance.setTime(time); if (qs.contains("pname")) { provenance.setUrl(qs.getLiteral("pname").getLexicalForm()); } if(qs.contains("tit")){ provenance.setTitle(qs.getLiteral("tit").getLexicalForm()); } if(qs.contains("sub")){ provenance.setSubTitle(qs.getLiteral("sub").getLexicalForm()); } if(qs.contains("lt")){ provenance.setTitle(qs.getLiteral("lt").getLexicalForm()); } if(qs.contains("la")){ provenance.setSubTitle(qs.getLiteral("la").getLexicalForm()); } if(qs.contains("blog")){ provenance.setBlog(qs.getResource("blog").getURI()); } return provenance; } private String createGetGuidesQuery(Integer limit, String uri) { StringBuilder query = new StringBuilder(""); query.append("SELECT distinct ?noticia ?title ?url ?dateG ?uriImage ?pnameImage ?titImage WHERE {"); query.append("?noticia <http://www.w3.org/2003/01/geo/wgs84_pos#location> <" + uri + ">."); query.append("?noticia a <http://webenemasuno.linkeddata.es/ontology/OPMO/Guide>."); query.append("OPTIONAL {?noticia <http://rdfs.org/sioc/ns#title> ?title . }"); query.append("OPTIONAL {?noticia <http://rdfs.org/sioc/ns#created_at> ?dateG . }"); query.append("OPTIONAL {?noticia <http://openprovenance.org/model/opmo#pname> ?url . }"); query.append("OPTIONAL {?gen <http://openprovenance.org/model/opmo#effect> ?noticia."); query.append("?gen <http://openprovenance.org/model/opmo#cause> ?process."); query.append("?used <http://openprovenance.org/model/opmo#effect> ?process."); query.append("?used <http://openprovenance.org/model/opmo#cause> ?uriImage."); query.append("?uriImage a <http://webenemasuno.linkeddata.es/ontology/OPMO/Image>."); query.append("?uriImage <http://openprovenance.org/model/opmo#pname> ?pnameImage.}"); query.append("OPTIONAL{?uriImage <http://metadata.net/mpeg7/mpeg7.owl#title> ?tittleImageUri."); query.append("?tittleImageUri <http://www.w3.org/2000/01/rdf-schema#label> ?titImage.}"); query.append("}"); if (limit != null) { query.append(" LIMIT " + limit); } return query.toString(); } private String createGetTripsQuery(Integer limit, String uri) { StringBuilder query = new StringBuilder( "SELECT distinct ?trip ?tripTitle ?tripURL ?created ?pL ?pH ?dL ?dH ?tD ?prL ?prH WHERE{ "); query.append("?trip <http://webenemasuno.linkeddata.es/ontology/OPMO/hasItinerary> <"+uri+">."); // URL query.append("OPTIONAL{?trip <http://openprovenance.org/model/opmo#pname> ?tripURL. }"); // title query.append("OPTIONAL{?trip <http://purl.org/dc/terms/title> ?tripTitle. }"); // created query.append("?trip <http://rdfs.org/sioc/ns#created_at> ?created."); // price query.append("OPTIONAL{?trip <http://webenemasuno.linkeddata.es/ontology/OPMO/hasPrice> ?p}."); query.append("OPTIONAL{?p <http://webenemasuno.linkeddata.es/ontology/OPMO/lessEurosThan> ?pL}."); query.append("OPTIONAL{?p <http://webenemasuno.linkeddata.es/ontology/OPMO/moreEurosThan> ?pH }."); // duration query.append("OPTIONAL{?trip <http://webenemasuno.linkeddata.es/ontology/OPMO/hasDuration> ?d}."); query.append("OPTIONAL{?d <http://webenemasuno.linkeddata.es/ontology/OPMO/lessWeeksThan> ?dL}."); query.append("OPTIONAL{?d <http://webenemasuno.linkeddata.es/ontology/OPMO/moreWeeksThan> ?dH }."); // description (if any) query.append("OPTIONAL{?trip <http://webenemasuno.linkeddata.es/ontology/OPMO/tripDescription> ?tD}."); // distance query.append("OPTIONAL{?trip <http://webenemasuno.linkeddata.es/ontology/OPMO/hasDistance> ?pr}."); query.append("OPTIONAL{?pr <http://webenemasuno.linkeddata.es/ontology/OPMO/lessKmThan> ?prL}."); query.append("OPTIONAL{?pr <http://webenemasuno.linkeddata.es/ontology/OPMO/moreKmThan> ?prH }."); query.append("}"); if (limit != null) { query.append(" LIMIT " + limit); } return query.toString(); } private String createGetTripProvenance(Integer limit, String uri) { StringBuilder query = new StringBuilder( "SELECT distinct ?reference ?time ?pname ?tit ?sub ?lt ?la ?blog ?nextV WHERE{ "); query.append("?gen <http://openprovenance.org/model/opmo#effect> <" + uri + ">."); query.append("?gen <http://openprovenance.org/model/opmo#cause> ?process."); query.append("?used <http://openprovenance.org/model/opmo#effect> ?process."); query.append("?used <http://openprovenance.org/model/opmo#cause> ?reference."); // date para el timeline query.append("OPTIONAL{?used <http://openprovenance.org/model/opmo#time> ?t."); query.append("?t <http://openprovenance.org/model/opmo#exactlyAt> ?time.}"); // pname es comun query.append("OPTIONAL{?reference <http://openprovenance.org/model/opmo#pname> ?pname}"); // GUIDE: title, description, rights, creator, RDF query.append("OPTIONAL{?reference <http://rdfs.org/sioc/ns#title> ?tit}"); query.append("OPTIONAL{?reference <http://webenemasuno.linkeddata.es/ontology/OPMO/subtitle> ?sub}"); // IMAGE-VIDEO: title, description, rights, creator, RDF query.append("OPTIONAL{?reference <http://metadata.net/mpeg7/mpeg7.owl#title> ?tI." + "?tI <http://www.w3.org/2000/01/rdf-schema#label> ?lt}."); query.append("OPTIONAL{?reference <http://metadata.net/mpeg7/mpeg7.owl#abstract> ?a." + "?a <http://www.w3.org/2000/01/rdf-schema#label> ?la}."); // POST: blog link query.append("OPTIONAL{?reference <http://rdfs.org/sioc/ns#has_container> ?blog}."); // title ya viene de guide // next Version query.append("OPTIONAL{?b <http://openprovenance.org/model/opmo#cause> <" + uri + ">."); query.append("?b a <http://webenemasuno.linkeddata.es/ontology/OPMO/LaterVersionThan>."); query.append("?b <http://openprovenance.org/model/opmo#effect> ?nextV }"); query.append("}"); if (limit != null) { query.append(" LIMIT " + limit); } return query.toString(); } private String getImageURL(String URL, int prevImages) { String convertedURL = getRedirectedURL(URL); convertedURL = convertedURL.replace("elviajero.elpais.com", "ep01.epimg.net"); convertedURL = convertedURL.replace("diario", "diario/imagenes"); convertedURL = convertedURL.replace(".html", "_" + String.format("%010d", prevImages) + "_sumario_normal.jpg"); if (!checkIfURLExists(convertedURL)) { return ""; } else { return convertedURL; } } private String getNewPname(String URL) { return getRedirectedURL(URL); } private String getRedirectedURL(String URL) { String toReturn = ""; HttpURLConnection con = null; try { con = (HttpURLConnection) new URL(URL).openConnection(); con.connect(); con.setInstanceFollowRedirects(false); int responseCode = con.getResponseCode(); if ((responseCode / 100) == 3) { String newLocationHeader = con.getHeaderField("Location"); responseCode = con.getResponseCode(); if (isRelativeURL(newLocationHeader)) { String urlFull = con.getURL().toString(); urlFull = urlFull.replaceAll(con.getURL().getPath(), newLocationHeader); toReturn = urlFull; } else { URL urlLocation = new URL(newLocationHeader); String urlFull = urlLocation.toString(); toReturn = urlFull; } } if ((responseCode / 100) == 2) { toReturn = URL; } } catch (MalformedURLException e) { logger.error(e); } catch (IOException e) { logger.error(e); } catch (Exception e) { // Nothing logger.error(e); } finally { if (con != null) { con.disconnect(); } } return toReturn; } private boolean isRelativeURL(String newLocationHeader) { try { URL urlLocation = new URL(newLocationHeader); if (urlLocation.getHost() == null || urlLocation.getHost().isEmpty() || urlLocation.getHost().equals("")) { return true; } return false; } catch (MalformedURLException e) { } catch (Exception e) { } return true; } private boolean checkIfURLExists(String URL) { boolean toReturn = false; HttpURLConnection con = null; try { con = (HttpURLConnection) new URL(URL).openConnection(); con.connect(); con.setInstanceFollowRedirects(false); int responseCode = con.getResponseCode(); if ((responseCode / 100) == 2) { toReturn = true; } if ((responseCode / 100) == 3) { String newURL = getRedirectedURL(URL); if (newURL != null && URL != null && URL.equals(newURL)) { return true; } if (newURL != null && !newURL.equals("") && !newURL.isEmpty()) { return checkIfURLExists(newURL); } } } catch (MalformedURLException e) { logger.error(e); } catch (IOException e) { logger.error(e); } catch (Exception e) { // Nothing to do logger.error(e); } finally { if (con != null) { con.disconnect(); } } return toReturn; } }