package eu.lod2.rsine.remotenotification; import eu.lod2.util.Namespaces; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.openrdf.model.*; import org.openrdf.model.impl.ValueFactoryImpl; import org.openrdf.model.vocabulary.RDF; import org.openrdf.rio.RDFHandlerException; import org.openrdf.rio.RDFWriter; import org.openrdf.rio.ntriples.NTriplesWriterFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.naming.ServiceUnavailableException; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; class RemoteNotificationService extends RemoteNotificationServiceBase { private final Logger logger = LoggerFactory.getLogger(RemoteNotificationService.class); private String authoritativeUri; public RemoteNotificationService(String authoritativeUri) { this.authoritativeUri = authoritativeUri; } @Override public void announce(Model changeSet) { Collection<Resource> extResources = getExternalResources(changeSet); try { for (Resource extResource : extResources) { notifyRemoteService(remoteServiceDetector.getRemoteService(extResource), changeSet); } } catch (ServiceUnavailableException e) { logger.warn("Remote service unavailable: " +e.getMessage()); } } private void notifyRemoteService(URI remoteService, Model changeSet) { addSourceInfo(changeSet); try { String ntriplesChangeSet = createNTriplesChangeSet(changeSet); postChangeSet(remoteService, ntriplesChangeSet); } catch (IOException e) { logger.error("Error posting changeset to '" +remoteService.stringValue()+ "': " +e.getMessage()); } catch (RDFHandlerException e) { logger.error("Error serializing changeset", e); } } private Collection<Resource> getExternalResources(Model changeSet) { Resource statement = changeSet.filter(null, RDF.STATEMENT, null).objectResource(); Value subject = changeSet.filter(statement, RDF.SUBJECT, null).objectValue(); Value object = changeSet.filter(statement, RDF.OBJECT, null).objectValue(); return filterExternalResources(subject, object); } private Collection<Resource> filterExternalResources(Value... values) { Collection<Resource> externalResources = new ArrayList<Resource>(); for (Value value : values) { if (value instanceof Resource && !value.stringValue().toUpperCase().contains(authoritativeUri.toUpperCase())) { logger.info("Recognized resource '" +value.stringValue()+ " as external"); externalResources.add((Resource) value); } } return externalResources; } private void addSourceInfo(Model changeSet) { ValueFactory valueFactory = new ValueFactoryImpl(); Resource changeSetRoot = changeSet.filter(null, valueFactory.createURI(Namespaces.CS_NAMESPACE.getName(), "createdDate"), null).subjects().iterator().next(); changeSet.add(valueFactory.createStatement( changeSetRoot, valueFactory.createURI(Namespaces.DCTERMS_NAMESPACE.getName(), "source"), valueFactory.createURI(authoritativeUri))); } private String createNTriplesChangeSet(Model changeSet) throws RDFHandlerException { StringWriter sw = new StringWriter(); RDFWriter writer = new NTriplesWriterFactory().getWriter(sw); writer.startRDF(); for (Statement st : changeSet) { writer.handleStatement(st); } writer.endRDF(); return sw.toString(); } private void postChangeSet(URI remoteService, String changeSet) throws IOException, RDFHandlerException { HttpPost httpPost = new HttpPost(remoteService.stringValue() + "/remote"); httpPost.setEntity(new StringEntity(changeSet)); HttpResponse response = new DefaultHttpClient().execute(httpPost); logger.info("Posted changeset to '" +remoteService+ "', response: " +response.getStatusLine().getStatusCode()); } }