package eu.geoknow.generator.component; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.validation.Valid; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; 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 com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.sparql.vocabulary.FOAF; import com.hp.hpl.jena.vocabulary.DC; import com.hp.hpl.jena.vocabulary.DCTerms; import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; import com.ontos.ldiw.vocabulary.LDIS; import eu.geoknow.generator.common.MediaType; import eu.geoknow.generator.common.Queries; import eu.geoknow.generator.component.beans.Component; import eu.geoknow.generator.component.beans.Service; import eu.geoknow.generator.component.beans.ServiceType; import eu.geoknow.generator.configuration.FrameworkConfiguration; import eu.geoknow.generator.exceptions.InformationMissingException; import eu.geoknow.generator.exceptions.ResourceExistsException; import eu.geoknow.generator.exceptions.ResourceNotFoundException; import eu.geoknow.generator.exceptions.SPARQLEndpointException; import eu.geoknow.generator.rdf.RdfStoreManager; public class ComponentManager { private static final Logger log = Logger.getLogger(ComponentManager.class); private static Collection<ServiceType> serviceTypes; private static FrameworkConfiguration config; private static RdfStoreManager storeManager; /** * Initialize the manager providing the corresponding manager of the user that will execute the * actions * * @param storeManager * @throws IOException * @throws InformationMissingException */ public ComponentManager(RdfStoreManager storeManager) throws IOException, InformationMissingException { config = FrameworkConfiguration.getInstance(); ComponentManager.storeManager = storeManager; } /** * Return a list of components and its services. For the moment this will provide all components * defined in the framework-components, but there is no distinguish between components that are * integrated in the workbench. * * @return List<Component> * @throws SPARQLEndpointException * @throws IOException */ public Collection<Component> getAllComponents() throws SPARQLEndpointException, IOException { Map<String, Component> components = new HashMap<String, Component>(); try { // get all components and the services list String query = "SELECT ?component ?label ?version ?homepage ?service ?sproperty ?sobject FROM <" + config.getComponentsGraph() + "> WHERE { ?component a <" + LDIS.StackComponent.getURI() + "> ; <" + RDFS.label.getURI() + "> ?label ; <" + DCTerms.hasVersion + "> ?version ; <" + FOAF.homepage.getURI() + "> ?homepage ; <" + LDIS.providesService + "> ?service . ?service ?sproperty ?sobject " + "} ORDER BY ?component"; log.debug(query); String result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(result); Iterator<JsonNode> bindingsIter = rootNode.path("results").path("bindings").elements(); while (bindingsIter.hasNext()) { JsonNode bindingNode = bindingsIter.next(); String curi = bindingNode.get("component").path("value").textValue(); String suri = bindingNode.get("service").path("value").textValue(); String property = bindingNode.get("sproperty").path("value").textValue(); String object = bindingNode.get("sobject").path("value").textValue(); if (!components.containsKey(curi)) { Component c = new Component(); c.setUri(curi); c.setLabel(bindingNode.get("label").path("value").textValue()); c.setVersion(bindingNode.get("version").path("value").textValue()); c.setHomepage(bindingNode.get("homepage").path("value").textValue()); Service s = new Service(); s.setUri(suri); setServiceProperty(s, property, object); c.getServices().add(s); components.put(c.getUri(), c); } else { boolean found = false; for (Service si : components.get(curi).getServices()) { if (si.getUri().equals(suri)) { setServiceProperty(si, property, object); found = true; break; } } if (!found) { Service s = new Service(); s.setUri(suri); setServiceProperty(s, property, object); components.get(curi).getServices().add(s); } } } } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } return components.values(); } /** * Get the component data * * @param id * @return Component or null if not found * @throws SPARQLEndpointException * @throws IOException * @throws ResourceNotFoundException */ public Component getComponent(String id) throws SPARQLEndpointException, IOException, ResourceNotFoundException { Component component = null; String uri = config.getResourceNamespace() + id; log.debug(config.getResourceNamespace()); try { // get all components and the services list String query = "SELECT ?label ?version ?homepage ?service ?sproperty ?sobject FROM <" + config.getComponentsGraph() + "> WHERE { <" + uri + "> a <" + LDIS.StackComponent.getURI() + "> ; <" + RDFS.label.getURI() + "> ?label ; <" + DCTerms.hasVersion + "> ?version ; <" + FOAF.homepage.getURI() + "> ?homepage ; <" + LDIS.providesService + "> ?service . ?service ?sproperty ?sobject " + " }"; log.debug(query); String result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(result); Iterator<JsonNode> bindingsIter = rootNode.path("results").path("bindings").elements(); while (bindingsIter.hasNext()) { JsonNode bindingNode = bindingsIter.next(); String suri = bindingNode.get("service").path("value").textValue(); String property = bindingNode.get("sproperty").path("value").textValue(); String object = bindingNode.get("sobject").path("value").textValue(); if (component == null) { component = new Component(); component.setUri(uri); component.setLabel(bindingNode.get("label").path("value").textValue()); component.setVersion(bindingNode.get("version").path("value").textValue()); component.setHomepage(bindingNode.get("homepage").path("value").textValue()); Service s = new Service(); s.setUri(suri); setServiceProperty(s, property, object); component.getServices().add(s); } else { boolean found = false; for (Service si : component.getServices()) { if (si.getUri().equals(suri)) { setServiceProperty(si, property, object); found = true; break; } } if (!found) { Service s = new Service(); s.setUri(suri); setServiceProperty(s, property, object); component.getServices().add(s); } } } } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } if (component == null) throw new ResourceNotFoundException(uri + " not found"); return component; } /** * Inserts a component with its services * * @param component a valid instance of Component * @throws IOException * @throws SPARQLEndpointException * @throws ResourceExistsException */ public Component addComponent(@Valid Component component) throws IOException, SPARQLEndpointException, ResourceExistsException { if (Queries.resourceExists(component.getUri(), storeManager)) throw new ResourceExistsException(component.getLabel() + " already exists as " + component.getUri()); String query = "INSERT DATA { GRAPH <" + config.getComponentsGraph() + "> { " + insertComponentStatements(component) + " }}"; log.debug(query); String result; try { result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } log.debug(result); return component; } /** * Inserts a service * * @param component a valid instance of Component * @throws IOException * @throws SPARQLEndpointException * @throws ResourceExistsException * @throws ResourceNotFoundException */ public Service addService(String uri, @Valid Service service) throws IOException, SPARQLEndpointException, ResourceExistsException, ResourceNotFoundException { // check that the component metadata exists if (!Queries.resourceExists(uri, storeManager)) throw new ResourceNotFoundException(uri + " doesnt exist "); // check that the service doesn't exists if (Queries.resourceExists(service.getUri(), storeManager)) throw new ResourceExistsException("Service " + service.getUri() + " already exist as " + service.getLabel()); String query = "INSERT DATA { GRAPH <" + config.getComponentsGraph() + "> { <" + uri + "> <" + LDIS.providesService.getURI() + "> <" + service.getUri() + ">. " + insertServiceStatements(service) + " }}"; log.debug(query); String result; try { result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } log.debug(result); return service; } /** * Update a component * * @param component * @throws IOException * @throws SPARQLEndpointException * @throws ResourceNotFoundException */ public Component updateComponent(Component component) throws IOException, SPARQLEndpointException, ResourceNotFoundException { // check that the component exists if (!Queries.resourceExists(component.getUri(), storeManager)) throw new ResourceNotFoundException(component.getUri() + " not found"); try { String query = "WITH <" + config.getComponentsGraph() + "> DELETE { <" + component.getUri() + "> ?s ?p ; <" + LDIS.providesService + "> ?service . ?service ?sproperty ?sobject } INSERT {" + insertComponentStatements(component) + "} WHERE { <" + component.getUri() + "> ?s ?p ; <" + LDIS.providesService + "> ?service . ?service ?sproperty ?sobject }"; log.debug(query); String result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); log.debug(result); // TODO: validate the result and return the component object if successful return component; } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } } /** * Delete a component with the given uri * * @param uri * @throws IOException * @throws SPARQLEndpointException */ public void deleteComponent(String uri) throws IOException, SPARQLEndpointException { try { String query = "WITH <" + config.getComponentsGraph() + "> DELETE { <" + uri + "> ?s ?p ; <" + LDIS.providesService + "> ?service . ?service ?sproperty ?sobject } WHERE { <" + uri + "> ?s ?p ; <" + LDIS.providesService + "> ?service . ?service ?sproperty ?sobject }"; log.debug(query); String result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); log.debug(result); } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } } /** * Delete a service with the given uri * * @param uri * @throws IOException * @throws SPARQLEndpointException */ public void deleteService(String uri) throws IOException, SPARQLEndpointException { try { String query = "WITH <" + config.getComponentsGraph() + "> DELETE { ?component <" + LDIS.providesService + "> <" + uri + "> . <" + uri + "> ?sproperty ?sobject } WHERE { < ?component <" + LDIS.providesService + "> <" + uri + "> . <" + uri + "> ?sproperty ?sobject }"; log.debug(query); String result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); log.debug(result); } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } } /** * Retreives existing types of services in the ldi-schema ontology * * @return Collection<ServiceType> collection with the existing services uris and labels * @throws IOException */ public Collection<ServiceType> getServiceTypes() throws IOException { if (serviceTypes == null) { Map<String, ServiceType> services = new HashMap<String, ServiceType>(); // read the ontology file and get the list String query = "SELECT ?uri ?label {?uri <" + RDFS.subClassOf.getURI() + "> <" + LDIS.ComponentService.getURI() + "> ; <" + RDFS.label.getURI() + "> ?label}"; log.debug(query); QueryExecution qexec = QueryExecutionFactory.create(query, LDIS.getModel()); ResultSet results = qexec.execSelect(); while (results.hasNext()) { QuerySolution soln = results.next(); String uri = soln.get("uri").asResource().getURI(); Literal literal = soln.get("label").asLiteral(); String language = literal.getLanguage(); if (literal.getLanguage().equals("")) language = "default"; ServiceType st = null; if (services.containsKey(uri)) st = services.get(uri); else { st = new ServiceType(); st.setUri(uri); services.put(uri, st); } st.getLabels().put(language, literal.getString()); } serviceTypes = services.values(); } return serviceTypes; } /** * Get all services from all components * * @return Collection<Service> object * @throws SPARQLEndpointException * @throws IOException */ public Collection<Service> getAllServices() throws SPARQLEndpointException, IOException { Map<String, Service> services = new HashMap<String, Service>(); try { // get all components and the services list String query = "SELECT ?service ?sproperty ?sobject FROM <" + config.getComponentsGraph() + "> WHERE { ?component <" + LDIS.providesService + "> ?service. ?service ?sproperty ?sobject " + "} "; log.debug(query); String result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(result); Iterator<JsonNode> bindingsIter = rootNode.path("results").path("bindings").elements(); while (bindingsIter.hasNext()) { JsonNode bindingNode = bindingsIter.next(); String subject = bindingNode.get("service").path("value").textValue(); String property = bindingNode.get("sproperty").path("value").textValue(); String object = bindingNode.get("sobject").path("value").textValue(); if (!services.containsKey(subject)) { Service s = new Service(); s.setUri(subject); setServiceProperty(s, property, object); services.put(subject, s); } else { Service s = services.get(subject); setServiceProperty(s, property, object); } } } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } return services.values(); } /** * Get the information of a service * * @param uri * @return Service object * @throws SPARQLEndpointException * @throws IOException */ public Service getService(String id) throws SPARQLEndpointException, IOException { String uri = config.getResourceNamespace() + id; Service service = new Service(); service.setUri(uri); try { // get all components and the services list String query = "SELECT ?sproperty ?sobject FROM <" + config.getComponentsGraph() + "> WHERE { <" + uri + "> ?sproperty ?sobject " + "} "; log.debug(query); String result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(result); Iterator<JsonNode> bindingsIter = rootNode.path("results").path("bindings").elements(); if (!bindingsIter.hasNext()) throw new ResourceNotFoundException(uri + " not found in the store"); while (bindingsIter.hasNext()) { JsonNode bindingNode = bindingsIter.next(); String property = bindingNode.get("sproperty").path("value").textValue(); String object = bindingNode.get("sobject").path("value").textValue(); setServiceProperty(service, property, object); } } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } return service; } /** * Update the data of a service * * @param pservice * @return Service object * @throws SPARQLEndpointException * @throws IOException * @throws ResourceNotFoundException */ public Service updateService(Service pservice) throws SPARQLEndpointException, IOException, ResourceNotFoundException { if (!Queries.resourceExists(pservice.getUri(), storeManager)) throw new ResourceNotFoundException(pservice.getUri() + " not found"); try { String query = "WITH <" + config.getComponentsGraph() + "> DELETE { <" + pservice.getUri() + "> ?sproperty ?sobject } INSERT {" + insertServiceStatements(pservice) + "} WHERE { <" + pservice.getUri() + "> ?sproperty ?sobject }"; log.debug(query); String result = storeManager.execute(query, MediaType.SPARQL_JSON_RESPONSE_FORMAT); log.debug(result); // TODO: validate the result and return the component object if successful } catch (Exception e) { e.printStackTrace(); throw new SPARQLEndpointException(e.getMessage()); } return pservice; } /** * Assigns literal properties to the Service object * * @param service * @param property as the URI of the porperty to set * @param value the value */ public static void setServiceProperty(Service s, String property, String value) { if (RDF.type.getURI().equals(property)) s.setType(value); else if (RDFS.label.getURI().equals(property)) s.setLabel(value); else if (LDIS.serviceUrl.getURI().equals(property)) s.setServiceUrl(value); else if (DC.description.getURI().equals(property)) s.setDescription(value); else { s.getProperties().put(property, value); } } /** * Given the component instance, this function will generate all triples for an insert query * * @param component * @return String containing the triples that can be used in a insert statement */ private String insertComponentStatements(Component component) { // get all components and the services list String servicesStatements = ""; for (Service s : component.getServices()) { servicesStatements += "<" + component.getUri() + "> <" + LDIS.providesService + "> <" + s.getUri() + "> ."; servicesStatements += insertServiceStatements(s); } // get all components and the services list String statemets = " <" + component.getUri() + "> a <" + LDIS.StackComponent.getURI() + "> ; <" + RDFS.label.getURI() + "> \"" + component.getLabel() + "\" ^^ xsd:string ; <" + DCTerms.hasVersion + "> \"" + component.getVersion() + "\" ^^ xsd:string ; <" + FOAF.homepage.getURI() + "> <" + component.getHomepage() + "> . " + servicesStatements + " "; return statemets; } /** * Given the service instance, this function will generate all triples for an insert query * * @param service * @return String containing the triples that can be used in a insert statement */ private String insertServiceStatements(Service service) { List<String> properties = new ArrayList<String>(); properties.add("<" + service.getUri() + "> a <" + service.getType() + "> ; <" + RDFS.label.getURI() + "> \"" + service.getLabel() + "\" ^^ xsd:string ; <" + DCTerms.description + "> \"" + service.getDescription() + "\" ; <" + LDIS.serviceUrl.getURI() + "> <" + service.getServiceUrl() + "> "); for (String p : service.getProperties().keySet()) properties.add("<" + p + "> \"" + service.getProperties().get(p) + "\" ^^ xsd:string "); String servicesStatements = StringUtils.join(properties, ";") + "."; log.debug(servicesStatements); return servicesStatements; } }