Package uk.ac.osswatch.simal.service.jena

Source Code of uk.ac.osswatch.simal.service.jena.JenaPersonService

package uk.ac.osswatch.simal.service.jena;
/*
* Copyright 2007 University of Oxford
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import uk.ac.osswatch.simal.SimalProperties;
import uk.ac.osswatch.simal.SimalRepositoryFactory;
import uk.ac.osswatch.simal.model.IPerson;
import uk.ac.osswatch.simal.model.IProject;
import uk.ac.osswatch.simal.model.jena.Person;
import uk.ac.osswatch.simal.model.jena.simal.JenaSimalRepository;
import uk.ac.osswatch.simal.model.simal.SimalOntology;
import uk.ac.osswatch.simal.rdf.AbstractSimalRepository;
import uk.ac.osswatch.simal.rdf.DuplicateURIException;
import uk.ac.osswatch.simal.rdf.ISimalRepository;
import uk.ac.osswatch.simal.rdf.SimalRepositoryException;
import uk.ac.osswatch.simal.rdf.io.RDFUtils;
import uk.ac.osswatch.simal.rdf.io.RDFXMLUtils;
import uk.ac.osswatch.simal.service.IPersonService;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;

public class JenaPersonService extends JenaService implements
    IPersonService {
  private static final Logger LOGGER = LoggerFactory
  .getLogger(JenaPersonService.class);

  public JenaPersonService(ISimalRepository simalRepository) {
    super(simalRepository);
  }

  public IPerson create(String uri) throws SimalRepositoryException,
      DuplicateURIException {
      if (getRepository().containsPerson(uri)) {
          throw new DuplicateURIException(
              "Attempt to create a second person with the URI " + uri);
        }
    Model model = ((JenaSimalRepository)getRepository()).getModel();

        String personID = getNewID();
        String simalPersonURI = RDFUtils.getDefaultPersonURI(personID);
        LOGGER.debug("Creating a new Simal Person instance with URI: "
            + simalPersonURI);

        com.hp.hpl.jena.rdf.model.Resource r = model.createResource(simalPersonURI);
        Statement s = model.createStatement(r, RDF.type, SimalOntology.PERSON);
        model.add(s);
       
        if (!uri.startsWith(RDFUtils.PERSON_NAMESPACE_URI)) {
          com.hp.hpl.jena.rdf.model.Resource res = model.createResource(uri);
          s = model.createStatement(r, RDFS.seeAlso, res);
          model.add(s);
        }

        IPerson person = new Person(r);
        person.setSimalID(personID);
        return person;
  }

  /**
   * Add a person to the repository. We attempt to handle duplicates by matching on items
   * such as email email hashes and seeAlso URIs.
   *
   * @param simalProjectURI
   *          the URI of the simal record representing the project this person beongs to
   * @throws DOMException
   * @throws SimalRepositoryException
   */
  public void addPerson(Element sourcePersonRoot, String simalProjectURI)
      throws SimalRepositoryException, DOMException {
    if (!sourcePersonRoot.getLocalName().equals("Person")) {
      throw new IllegalArgumentException(
          "Supplied element is not a doap:Person element, it is "
              + sourcePersonRoot.getNodeName());
    }
    String simalPersonURI = null;
   
    cleanPerson(sourcePersonRoot);
    RDFXMLUtils.checkPersonSHA1(sourcePersonRoot.getOwnerDocument());

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    DocumentBuilder db;
    try {
      db = dbf.newDocumentBuilder();
    } catch (ParserConfigurationException e) {
      throw new SimalRepositoryException("Unable to create document builder", e);
    }
    Document simalPersonDoc = db.newDocument();
    Node simalPersonRDFRoot = simalPersonDoc.createElementNS(RDFUtils.RDF_NS,
        "RDF");
    Element simalPersonElement = simalPersonDoc.createElementNS(
        RDFUtils.SIMAL_NS, "Person");

    // handle duplicate people identified by their mbox_sha1sum
    NodeList sha1sums = sourcePersonRoot.getElementsByTagNameNS(
        RDFUtils.FOAF_NS, "mbox_sha1sum");
    for (int i = 0; i < sha1sums.getLength(); i = i + 1) {
      Element sha1sumNode = (Element) sha1sums.item(i);
      if (sha1sumNode.getParentNode().equals(sourcePersonRoot)) {
        String sha1Sum = sha1sumNode.getFirstChild().getNodeValue().trim();
        IPerson person = SimalRepositoryFactory.getPersonService().findBySha1Sum(sha1Sum);
        if (person != null) {
          LOGGER
              .debug("Simal already has a Person record with the foaf:mbox_sha1: "
                  + sha1Sum + " called " + person);
          person = SimalRepositoryFactory.getPersonService().findBySeeAlso(person.getURI());
          simalPersonURI = person.getURI();
        }
      }
    }

    // handle duplicate people identified by their rdf:about
    String uri = sourcePersonRoot.getAttributeNS(RDFUtils.RDF_NS, "about");
    IPerson person = SimalRepositoryFactory.getPersonService().findBySeeAlso(uri);
    if (person != null) {
      LOGGER
          .debug("Simal already has a Person record about "
                  + uri + " called " + person);
      simalPersonURI = person.getURI();
    }

    // handle duplicate people identified by their rdfs:seeAlso
    NodeList seeAlsos = sourcePersonRoot.getElementsByTagNameNS(
        RDFUtils.RDFS_NS, "seeAlso");
    Element seeAlso;
    for (int i = 0; i < seeAlsos.getLength(); i = i + 1) {
      seeAlso = (Element) seeAlsos.item(i);
      if (seeAlso.getParentNode().equals(sourcePersonRoot)) {
        uri = seeAlso.getAttributeNS(RDFUtils.RDF_NS, "resource").trim();
        person = SimalRepositoryFactory.getPersonService().findBySeeAlso(uri);
        if (person != null) {
          LOGGER
              .debug("Simal already has a Person record with the rdfs:seeAlso "
                  + uri + " called " + person);
          simalPersonURI = person.getURI();
        } else {
          seeAlso = simalPersonDoc.createElementNS(RDFUtils.RDFS_NS, "seeAlso");
          seeAlso.setAttributeNS(RDFUtils.RDF_NS, "resource", uri);
          simalPersonElement.appendChild(seeAlso);
        }
      }
    }

    // Add current project records
    Element projNode = simalPersonDoc.createElementNS(RDFUtils.FOAF_NS,
      "currentProject");
    projNode.setAttributeNS(RDFUtils.RDF_NS, "resource", simalProjectURI);
    simalPersonElement.appendChild(projNode);

    if (simalPersonURI == null) {
      String personID = getNewPersonID();
      simalPersonURI = RDFUtils.getDefaultPersonURI(personID);
      LOGGER.debug("Creating a new Simal Person instance with URI: "
          + simalPersonURI);

      Element simalID = simalPersonDoc.createElementNS(RDFUtils.SIMAL_NS,
          RDFUtils.SIMAL_PERSON_ID);
      simalID.setTextContent(personID);
      simalPersonElement.appendChild(simalID);
    } else {
      LOGGER.debug("Updating an existing Simal Person instance with URI: "
          + simalPersonURI);
    }
    simalPersonElement.setAttributeNS(RDFUtils.RDF_NS, "about", simalPersonURI);

    seeAlso = simalPersonDoc.createElementNS(RDFUtils.RDFS_NS, "seeAlso");
    String resource = sourcePersonRoot.getAttributeNS(RDFUtils.RDF_NS, "about");
    if (resource == null || resource.equals("")) {
      // we don't allow blank person nodes
      resource = RDFUtils.getDefaultPersonURI(getNewPersonID());
      sourcePersonRoot.setAttributeNS(RDFUtils.RDF_NS, "about", resource);
    }
    seeAlso.setAttributeNS(RDFUtils.RDF_NS, "resource", resource);
    simalPersonElement.appendChild(seeAlso);

    simalPersonRDFRoot.appendChild(simalPersonElement);
    simalPersonDoc.appendChild(simalPersonRDFRoot);

    RDFXMLUtils.addRDFXMLToModel(simalPersonDoc, getModel());

    // Handle all known people
    NodeList people = sourcePersonRoot.getElementsByTagNameNS(RDFUtils.FOAF_NS,
        "Person");
    Element personEl;
    for (int i = 0; i < people.getLength(); i = i + 1) {
      personEl = (Element) people.item(i);
      addPerson(personEl, simalProjectURI);
    }

    // add the source RDF
    Document sourceDoc = db.newDocument();
    Node root = sourceDoc.createElementNS(RDFUtils.RDF_NS, "RDF");
    root.appendChild(sourceDoc.importNode(sourcePersonRoot, true));
    sourceDoc.appendChild(root);
    RDFXMLUtils.addRDFXMLToModel(sourceDoc, getModel());
  }

  /**
   * Check the RDF for a person element for common mistakes and try to fix them.
   *
   * @param personRoot
   */
  private void cleanPerson(Element personRoot) {
    RDFXMLUtils.validateResourceDefinition(personRoot.getElementsByTagNameNS(
        RDFUtils.FOAF_NS, "homepage"));
  }
 
  public Set<IPerson> filterByName(String filter) {
    String queryStr = "PREFIX xsd: <" + AbstractSimalRepository.XSD_NAMESPACE_URI
      + "> " + "PREFIX foaf: <" + RDFUtils.FOAF_NS + "> "
      + "PREFIX rdf: <" + AbstractSimalRepository.RDF_NAMESPACE_URI + "> "
      + "PREFIX rdfs: <" + AbstractSimalRepository.RDFS_NAMESPACE_URI + "> "
      + "PREFIX simal: <" + AbstractSimalRepository.SIMAL_NAMESPACE_URI + "> "
      + "SELECT DISTINCT ?person WHERE { ?person a simal:Person; rdfs:seeAlso ?fp . "
      + " ?fp   foaf:name ?name . "
      + "FILTER regex(?name, \"" + convertFilterToRE(filter) + "\", \"i\") }";

      return filterBySPARQL(queryStr);
  }

  /**
     * Find all people returned using a SPARQL query.
     *
     * @param queryStr
     * @return
     */
    private Set<IPerson> filterBySPARQL(String queryStr) {
      Model model = ((JenaSimalRepository)getRepository()).getModel();
      Query query = QueryFactory.create(queryStr);
      QueryExecution qe = QueryExecutionFactory.create(query, model);
      ResultSet results = qe.execSelect();

      Set<IPerson> people = new HashSet<IPerson>();
      while (results.hasNext()) {
        QuerySolution soln = results.nextSolution();
        RDFNode node = soln.get("person");
        if (node.isResource()) {
          people.add(new Person((com.hp.hpl.jena.rdf.model.Resource) node));
        }
      }
      qe.close();
      return people;
    }

  public IPerson findById(String id) throws SimalRepositoryException {
      if (!getRepository().isValidSimalID(id)) {
          throw new SimalRepositoryException(
              "Attempt to find a person using an invalid Simal ID of "
                  + id
                  + " are you sure that's a world unique identifier? You may need to call getUniqueSimalID() or RDFUtils.getUniqueSimalID(id)");
        }
        String queryStr = "PREFIX xsd: <" + AbstractSimalRepository.XSD_NAMESPACE_URI
            + "> " + "PREFIX rdf: <" + AbstractSimalRepository.RDF_NAMESPACE_URI + ">"
            + "PREFIX simal: <" + AbstractSimalRepository.SIMAL_NAMESPACE_URI + ">"
            + "SELECT DISTINCT ?person WHERE { " + "?person simal:personId \"" + id
            + "\" }";
        IPerson person = findBySPARQL(queryStr);

        return person;
  }

    /**
     * Find a single person by executing a SPARQL query.
     *
     * @param queryStr
     * @return
     */
    private IPerson findBySPARQL(String queryStr) {
      Model model = ((JenaSimalRepository)getRepository()).getModel();
      Query query = QueryFactory.create(queryStr);
      QueryExecution qe = QueryExecutionFactory.create(query, model);
      ResultSet results = qe.execSelect();

      IPerson person = null;
      while (results.hasNext()) {
        QuerySolution soln = results.nextSolution();
        RDFNode node = soln.get("person");
        if (node.isResource()) {
          person = new Person((com.hp.hpl.jena.rdf.model.Resource) node);
        }
      }
      qe.close();
      return person;
    }

  public IPerson findBySeeAlso(String seeAlso)
      throws SimalRepositoryException {
    String queryStr = "PREFIX simal: <" + RDFUtils.SIMAL_NS + "> "
        + "PREFIX rdf: <" + AbstractSimalRepository.RDF_NAMESPACE_URI + "> "
        + "PREFIX rdfs: <" + AbstractSimalRepository.RDFS_NAMESPACE_URI + "> "
        + "SELECT DISTINCT ?person WHERE { "
        + "?person rdf:type simal:Person . " + "?person rdfs:seeAlso <"
        + seeAlso + ">}";

    IPerson person = findBySPARQL(queryStr);

    return person;
  }

  public IPerson findBySha1Sum(String sha1sum)
      throws SimalRepositoryException {
    String queryStr = "PREFIX foaf: <" + RDFUtils.FOAF_NS + "> "
        + "SELECT DISTINCT ?person WHERE { " + "?person foaf:mbox_sha1sum \""
        + sha1sum + "\"}";

    IPerson person = findBySPARQL(queryStr);

    return person;
  }

  public IPerson findByUsername(String username) {
    String queryStr = "PREFIX simal: <" + SimalOntology.NS + "> "
    + "SELECT DISTINCT ?person WHERE { " + "?person simal:username \""
    + username + "\"}";

    IPerson person = findBySPARQL(queryStr);
   
    return person;
  }

  public IPerson get(String uri) throws SimalRepositoryException {
    Model model = ((JenaSimalRepository)getRepository()).getModel();
    if(uri.startsWith(RDFUtils.PERSON_NAMESPACE_URI)) {
        if (getRepository().containsPerson(uri)) {
          return new Person(model.getResource(uri));
        } else {
          return null;
        }
    } else {
      return findBySeeAlso(uri);
    }
  }

  public Set<IPerson> getAll() throws SimalRepositoryException {
    Model model = ((JenaSimalRepository)getRepository()).getModel();
      Property o = model.createProperty(JenaSimalRepository.SIMAL_PERSON_URI);
      StmtIterator itr = model.listStatements(null, RDF.type, o);
      Set<IPerson> people = new HashSet<IPerson>();
      while (itr.hasNext()) {
        String uri = itr.nextStatement().getSubject().getURI();
        people.add(new Person(model.getResource(uri)));
      }
      return people;
  }

  public String getAllAsJSON() throws SimalRepositoryException {
      StringBuffer json = new StringBuffer("{ \"items\": [");
      Set<IPerson> setOfPeople = getAll();
      Iterator<IPerson> people = setOfPeople.iterator();
      IPerson person;
      while (people.hasNext()) {
        person = people.next();
        json.append(person.toJSONRecord());
        if (people.hasNext()) {
          json.append(",");
        }
      }
      json.append("]}");
      return json.toString();
  }

  public IPerson getDuplicate(String email) throws SimalRepositoryException {
    // TODO Auto-generated method stub
    return null;
  }

  public String getNewID() throws SimalRepositoryException {
    return getNewID(SimalProperties.PROPERTY_SIMAL_NEXT_PERSON_ID, "per");
  }

  public IPerson getOrCreate(String uri) throws SimalRepositoryException {
    if (SimalRepositoryFactory.getInstance().containsResource(uri)) {
      return SimalRepositoryFactory.getPersonService().get(uri);
    } else {
      IPerson person = findBySeeAlso(uri);
      if (person == null) {
        try {
          return SimalRepositoryFactory.getPersonService().create(uri);
        } catch (DuplicateURIException e) {
          LOGGER.error("Threw a DuplicateURIEception when we had already checked for resource existence", e);
          return null;
        }
      } else {
        return person;
      }
    }
  }

  public Set<IPerson> getColleagues(IPerson person) throws SimalRepositoryException {
      Set<IPerson> colleagues = new HashSet<IPerson>();
      Set<String> colleagueIDs = new HashSet<String>();
     
      Iterator<IProject> projects = person.getProjects().iterator();
      while (projects.hasNext()) {
        IProject project = projects.next();
        Iterator<IPerson> people = project.getAllPeople().iterator();
        while (people.hasNext()) {
          IPerson colleague = people.next();
          String id = colleague.getSimalID();
          if (!id.equals(person.getSimalID()) && !colleagueIDs.contains(id)) {
            colleagues.add(colleague);
            colleagueIDs.add(id);
          }
        }
      }

      return colleagues;
  }

  public IPerson createFromFoaf(Node node) {
    throw new UnsupportedOperationException();
  }

  public String getNewPersonID() throws SimalRepositoryException {
    String fullID = null;
    String strEntityID = SimalProperties.getProperty(
        SimalProperties.PROPERTY_SIMAL_NEXT_PERSON_ID, "1");
    long entityID = Long.parseLong(strEntityID);

    /**
     * If the properties file is lost for any reason the next ID value will be
     * lost. We therefore need to perform a sanity check that this is unique.
     */
    boolean validID = false;
    while (!validID) {
      fullID = SimalRepositoryFactory.getInstance().getUniqueSimalID("per" + Long.toString(entityID));
      if (SimalRepositoryFactory.getPersonService().findById(fullID) == null) {
        validID = true;
      } else {
        entityID = entityID + 1;
      }
    }

    long newId = entityID + 1;
    SimalProperties.setProperty(SimalProperties.PROPERTY_SIMAL_NEXT_PERSON_ID,
        Long.toString(newId));
    try {
      SimalProperties.save();
    } catch (Exception e) {
      LOGGER.warn("Unable to save properties file", e);
      throw new SimalRepositoryException(
          "Unable to save properties file when creating the next person ID", e);
    }

    return fullID;
  }

}
TOP

Related Classes of uk.ac.osswatch.simal.service.jena.JenaPersonService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.