/** * Globalize a gNode into a data object. * * @param gNode The graph node to globalize * @return A {@link org.jrdf.graph.Node} for the given graph node. * @throws QueryException If a globalize exception is encountered. */ public Node globalize(long gNode) throws QueryException { try { return session.globalize(gNode); } catch (GlobalizeException te) { throw new QueryException("Unable to globalize id <" + gNode + ">", te); } }
/** * Resolve a constraint against an RDF/XML document. * * <p>Resolution is by filtration of a URL stream, and thus very slow. */ public Resolution resolve(Constraint constraint) throws QueryException { if (logger.isDebugEnabled()) { logger.debug("Resolve " + constraint); } // Validate "constraint" parameter if (constraint == null) { throw new IllegalArgumentException("Null \"constraint\" parameter"); } if (!(constraint.getModel() instanceof LocalNode)) { if (logger.isDebugEnabled()) logger.debug("Ignoring solutions for " + constraint); return new EmptyResolution(constraint, false); } if (!(constraint.getElement(1) instanceof LocalNode) || !(constraint.getElement(2) instanceof LocalNode)) { throw new QueryException( "Prefix resolver can only be used for fixed prefixes: " + constraint); } try { long property = ((LocalNode) constraint.getElement(1)).getValue(); LocalNode object = (LocalNode) constraint.getElement(2); Node prefixNode = resolverSession.globalize(object.getValue()); // check the constraint for consistency if ((property != mulgaraPrefix && property != mulgaraStringPrefix) || !(prefixNode instanceof Literal || prefixNode instanceof URIReference)) { logger.debug("property = " + property + ", mulgaraPrefix = " + mulgaraPrefix); logger.debug("element(2): " + prefixNode + " [" + prefixNode.getClass().getName() + "]"); throw new QueryException( "Prefix resolver can only be used for prefix constraints: " + constraint); } if (logger.isDebugEnabled()) { logger.debug( "Evaluating " + constraint.getElement(0) + " has prefix " + constraint.getElement(2)); } ConstraintElement node = constraint.getElement(0); assert node != null; Tuples tuples; if (node instanceof Variable) { // convert the prefix into a string pool object SPObjectFactory spoFact = SPObjectFactoryImpl.getInstance(); SPObject startPrefixObj = getStartObject(spoFact, prefixNode, property); SPObject endPrefixObj = getEndObject(spoFact, prefixNode, property); // get the extents of the prefix from the string pool tuples = resolverSession.findStringPoolRange(startPrefixObj, true, endPrefixObj, false); assert tuples != null; // rename variables away from subject, predicate and object tuples.renameVariables(constraint); long resultSize; try { // Get the size of the final result. resultSize = tuples.getRowCount(); } catch (TuplesException e) { throw new QueryException("Unable to build result", e); } if (logger.isDebugEnabled()) { try { logger.debug( "tuples size = " + tuples.getRowCount() + " (should be " + resultSize + ")"); } catch (TuplesException e) { logger.debug("Error getting the length of the tuples object"); } } return new TuplesWrapperResolution(tuples, constraint); } else { // if (node instanceof Variable) // node must therefore be an instanceof LocalNode // we can shortcut the process here assert node instanceof LocalNode; LocalNode n = (LocalNode) node; // get the node out of the string pool SPObject spo = resolverSession.findStringPoolObject(n.getValue()); // check that the node exists if (spo == null) { tuples = TuplesOperations.empty(); } else { // see if the node starts with the required prefix String prefix; // extract the string from the literal if (prefixNode instanceof Literal) { prefix = ((Literal) prefixNode).getLexicalForm(); } else { prefix = ((URIReference) prefixNode).getURI().toString(); } if (spo.getLexicalForm().startsWith(prefix)) { tuples = TuplesOperations.unconstrained(); } else { tuples = TuplesOperations.empty(); } } } // convert the tuples to a resolution return new TuplesWrapperResolution(tuples, constraint); } catch (GlobalizeException ge) { throw new QueryException("Couldn't convert internal data into a string", ge); } catch (StringPoolException e) { throw new QueryException("Couldn't query constraint", e); } }
/** Insert or delete RDF statements in a model at a URL. */ public void modifyModel(long model, Statements statements, boolean occurs) throws ResolverException { if (logger.isDebugEnabled()) { logger.debug("Modify URL model " + model); } try { FullTextStringIndex stringIndex = getFullTextStringIndex(model); statements.beforeFirst(); while (statements.next()) { Node subjectNode = resolverSession.globalize(statements.getSubject()); // Do not insert the triple if it contains a blank node in subject. if (subjectNode instanceof BlankNode) { if (logger.isInfoEnabled()) { logger.info(statements.getSubject() + " is blank node; ignoring Lucene insert."); } continue; } Node predicateNode = resolverSession.globalize(statements.getPredicate()); Node objectNode = resolverSession.globalize(statements.getObject()); // Get the subject's string value. String subject = ((URIReference) subjectNode).getURI().toString(); // Predicates can only ever be URIReferences. String predicate = ((URIReference) predicateNode).getURI().toString(); if (objectNode instanceof URIReference) { URIReference objectURI = (URIReference) objectNode; String resource = objectURI.getURI().toString(); try { // Assert or deny the statement in the Lucene model if (occurs) { InputStream input = null; Reader reader = null; try { // Connect to the resource's content URLConnection connection = objectURI.getURI().toURL().openConnection(); String contentType = connection.getContentType(); if (logger.isDebugEnabled()) { logger.debug("Content type of resource is " + contentType); } MimeType contentMimeType; try { contentMimeType = new MimeType(contentType); } catch (MimeTypeParseException e) { logger.warn("\"" + contentType + "\" didn't parse as MIME type", e); try { contentMimeType = new MimeType("content", "unknown"); } catch (MimeTypeParseException em) { throw new ResolverException("Failed to create mime-type", em); } } assert contentMimeType != null; // If no character encoding is specified, guess at Latin-1 String charSet = contentMimeType.getParameter("charset"); if (charSet == null) { charSet = "ISO8859-1"; } assert charSet != null; // Get the content, performing appropriate character encoding input = connection.getInputStream(); reader = new InputStreamReader(input, charSet); // Add a filter if the content type is text/html, to strip out // HTML keywords that will clutter the index try { if (contentMimeType.match(new MimeType("text", "html"))) { reader = HtmlToTextConverter.convert(reader); } } catch (MimeTypeParseException em) { throw new ResolverException("Failed to create mime-type", em); } if (logger.isDebugEnabled()) { logger.debug("Inserting " + subject + " " + predicate + " " + resource); } if (!stringIndex.add(subject, predicate, resource, reader)) { logger.warn( "Unable to add {" + subject + ", " + predicate + ", " + resource + "} to full text string index"); } } catch (MalformedURLException e) { logger.info(resource + " is not a URL; ignoring Lucene insert"); } catch (IOException e) { throw new ResolverException("Can't obtain content of " + resource, e); } catch (org.mulgara.util.conversion.html.ParseException e) { throw new ResolverException("Couldn't parse content of " + resource, e); } finally { try { if (reader != null) reader.close(); else if (input != null) input.close(); } catch (IOException e) { logger.warn("Ignoring error closing resource content", e); } } } else { // (!occurs) if (logger.isDebugEnabled()) { logger.debug("Deleting " + subject + " " + predicate + " " + resource); } if (!stringIndex.remove(subject, predicate, resource)) { logger.warn( "Unable to remove {" + subject + ", " + predicate + ", " + resource + "} from full text string index"); } } } catch (FullTextStringIndexException e) { throw new ResolverException("Unable to modify full text index\n" + new StackTrace(e)); } } else if (objectNode instanceof Literal) { Literal objectLiteral = (Literal) objectNode; String literal = objectLiteral.getLexicalForm(); // Insert the statement into the text index try { if (occurs) { if (logger.isDebugEnabled()) { logger.debug("Inserting " + subject + " " + predicate + " " + literal); } if (!stringIndex.add(subject, predicate, literal)) { logger.warn( "Unable to add {" + subject + ", " + predicate + ", " + literal + "} to full text string index"); } } else { if (logger.isDebugEnabled()) { logger.debug("Deleting " + subject + " " + predicate + " " + literal); } if (!stringIndex.remove(subject, predicate, literal)) { logger.warn( "Unable to remove {" + subject + ", " + predicate + ", " + literal + "} from full text string index"); } } } catch (FullTextStringIndexException e) { throw new ResolverException( "Unable to " + (occurs ? "add" : "delete") + "'" + literal + "' to full text string index\n" + new StackTrace(e)); } } else { if (logger.isInfoEnabled()) { logger.info(objectNode + " is blank node; ignoring Lucene insert."); } } } } catch (TuplesException et) { throw new ResolverException("Error fetching statements", et); } catch (GlobalizeException eg) { throw new ResolverException("Error localizing statements", eg); } catch (IOException ioe) { throw new ResolverException("Failed to open string index", ioe); } catch (FullTextStringIndexException ef) { throw new ResolverException("Error in string index\n" + new StackTrace(ef)); } }