/* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Kowari Metadata Store. * * The Initial Developer of the Original Code is Plugged In Software Pty * Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002 * Plugged In Software Pty Ltd. All Rights Reserved. * * Contributor(s): N/A. * * [NOTE: The text of this Exhibit A may differ slightly from the text * of the notices in the Source Code files of the Original Code. You * should use the text of this Exhibit A rather than the text found in the * Original Code Source Code for Your Modifications.] * */ package org.mulgara.resolver; // Java 2 standard packages import java.net.URI; import java.util.*; // Third party packages import org.apache.log4j.Logger; import org.jrdf.graph.*; // Local packages import org.mulgara.content.ContentHandlerManager; import org.mulgara.jrdf.*; import org.mulgara.query.*; import org.mulgara.query.rdf.LiteralImpl; import org.mulgara.query.rdf.URIReferenceImpl; import org.mulgara.resolver.spi.*; import org.mulgara.server.*; import org.mulgara.store.statement.StatementStore; import org.mulgara.transaction.TransactionManagerFactory; /** * A JRDF database session. * * @created 2004-10-26 * * @author Andrew Newman * * @version $Revision: 1.11 $ * * @modified $Date: 2005/05/19 08:43:59 $ by $Author: raboczi $ * * @maintenanceAuthor $Author: raboczi $ * * @copyright ©2004 <a href="http://www.tucanatech.com/">Tucana * Technology, Inc</a> * * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ public class LocalJRDFDatabaseSession extends DatabaseSession implements LocalJRDFSession { /** * Logger. */ private static final Logger logger = Logger.getLogger(LocalJRDFDatabaseSession.class.getName()); /** * JRDF Graph */ protected JRDFFactory jrdfFactory; /** * Construct a database session. * * @param transactionManager the source of transactions for this session, * never <code>null</code> * @param securityAdapterList {@link List} of {@link SecurityAdapter}s to be * consulted before permitting operations, never <code>null</code> * @param symbolicTransformationList {@link List} of * {@link SymbolicTransformation}s to apply * @param resolverSessionFactory source of {@link ResolverSessionFactory}s, * never <code>null</code> * @param systemResolverFactory Source of {@link SystemResolver}s to manage * persistent models, for instance the system model (<code>#</code>); never * <code>null</code> * @param temporaryResolverFactory Source of {@link Resolver}s to manage * models which only last the duration of a transaction, for instance the * contents of external RDF/XML documents; never <code>null</code> * @param resolverFactoryList the list of registered {@link ResolverFactory} * instances to use for constraint resolution, never <code>null</code> * @param externalResolverFactoryMap map from URL protocol {@link String}s * to {@link ResolverFactory} instances for models accessed via that * protocol, never <code>null</code> * @param internalResolverFactoryMap map from model type {@link LocalNode}s * to {@link ResolverFactory} instances for that model type, never * <code>null</code> * @param metadata even more parameters from the parent {@link Database}, * never <code>null</code> * @param contentHandlers contains the list of valid registered content * handlers, never <code>null</code> * @param cachedResolverFactorySet contains the resolver factories that are * to have access to their models cached, never <code>null</code> * never <code>null</code> * @param temporaryModelTypeURI the type of model to use as a cache for * external models * @throws IllegalArgumentException if any argument is <code>null</code> */ LocalJRDFDatabaseSession(MulgaraTransactionManager transactionManager, TransactionManagerFactory transactionManagerFactory, List<SecurityAdapter> securityAdapterList, List<SymbolicTransformation> symbolicTransformationList, ResolverSessionFactory resolverSessionFactory, SystemResolverFactory systemResolverFactory, ResolverFactory temporaryResolverFactory, List<ResolverFactory> resolverFactoryList, Map<String,ResolverFactory> externalResolverFactoryMap, Map<URI,InternalResolverFactory> internalResolverFactoryMap, DatabaseMetadata metadata, ContentHandlerManager contentHandlers, Set<ResolverFactory> cachedResolverFactorySet, URI temporaryModelTypeURI, long transactionTimeout, long idleTimeout) throws ResolverFactoryException { super(transactionManager, transactionManagerFactory, securityAdapterList, symbolicTransformationList, resolverSessionFactory, systemResolverFactory, temporaryResolverFactory, resolverFactoryList, externalResolverFactoryMap, internalResolverFactoryMap, metadata, contentHandlers, cachedResolverFactorySet, temporaryModelTypeURI, transactionTimeout, idleTimeout, null); jrdfFactory = new JRDFFactoryImpl(); } public boolean contains(URI modelURI, SubjectNode subject, PredicateNode predicate, ObjectNode object) throws GraphException { Answer answer = find(modelURI, subject, predicate, object); try { return answer.getRowCardinality() > 0; } catch (TuplesException tuplesException) { throw new GraphException("Failed to determine if Graph contains Triple.", tuplesException); } finally { try { answer.close(); } catch (TuplesException tuplesException) { //cant do anything... logger.warn("Failed to close Answer.", tuplesException); } } } @SuppressWarnings("unchecked") public Answer find(URI modelURI, SubjectNode subject, PredicateNode predicate, ObjectNode object) throws GraphException { try { //select $Subject $Predicate $Object Variable[] vars = new Variable[3]; vars[0] = StatementStore.VARIABLES[0]; vars[1] = StatementStore.VARIABLES[1]; vars[2] = StatementStore.VARIABLES[2]; ConstraintImpl varConstraint = new ConstraintImpl(vars[0], vars[1], vars[2]); //where $s $p $o ConstraintExpression constraint = varConstraint; //and $s <is> <s> constraint = appendMulgaraIsConstraint(vars[0], toValue(subject), constraint); //and $p <is> <p> constraint = appendMulgaraIsConstraint(vars[1], toValue(predicate), constraint); //and $o <is> <o> constraint = appendMulgaraIsConstraint(vars[2], toValue(object), constraint); Query query = new Query( Arrays.asList(vars), // variable list new GraphResource(modelURI), // model expression constraint, // constraint expr null, // no having (List<Order>)Collections.EMPTY_LIST, // no ordering null, // no limit 0, // zero offset true, // distinct results new UnconstrainedAnswer() // nothing given ); //Execute! Answer answer = query(query); return answer; } catch (QueryException qe) { throw new GraphException("Failed to find the given triple pattern in " + " the model.", qe); } } /** * If the node is not null, a "and [var] <MULGARA:is> [node]" is appended to the * ConstraintExpression. * * If the node is null, the ConstraintExpression is returned unchanged. * * @param var Variable * @param node Value * @param expression ConstraintExpression * @throws QueryException * @return ConstraintExpression */ private ConstraintExpression appendMulgaraIsConstraint(Variable var, Value node, ConstraintExpression expression) throws QueryException { if (var == null) { throw new IllegalArgumentException("Variable is null."); } if (node != null) { ConstraintExpression constraint = new ConstraintIs(var, node); return new ConstraintConjunction(expression, constraint); } else { return expression; } } /** * Returns the number of triples in the graph. * * @return the number of triples in the graph. */ public long getNumberOfTriples(URI graphURI) { Answer allTriples = null; try { allTriples = find(graphURI, null, null, null); return allTriples.getRowCount(); } catch (GraphException ge) { logger.error("Failed to find statements", ge); return 0l; } catch (TuplesException tuplesException) { logger.error("Failed to determine number of statements", tuplesException); return 0l; } finally { //try to close the Answer if (allTriples != null) { try { allTriples.close(); } catch (TuplesException tuplesException) { logger.warn("Failed to close Answer.", tuplesException); } } } } /** * Returns the JRDF node factory. * * @return JRDF graph factory. */ public JRDFFactory getJRDFFactory() { return jrdfFactory; } /** * Convert a {@link Node} into a {@link Value}. * * @param node the JRDF {@link Node} to convert * @return an equivalent {@link Node} which is also a {@link Value} */ private Value toValue(Node node) throws QueryException { //short circuit if the node is null if (node == null) { return null; } // Short circuit if the "node" is already a Value if (node instanceof Value) { return (Value) node; } //convert URIReference or Literal Nodes only if (node instanceof URIReference) { return new URIReferenceImpl(((URIReference) node).getURI()); } else if (node instanceof Literal) { Literal literal = (Literal) node; String lexicalForm = literal.getLexicalForm(); String lang = literal.getLanguage(); URI type = literal.getDatatypeURI(); if (type != null) { return new LiteralImpl(lexicalForm, type); } else if (lang != null) { return new LiteralImpl(lexicalForm, lang); } else { return new LiteralImpl(lexicalForm); } } //node must be external BlankNode throw new QueryException("Conversion of alien BlankNodes not implemented: " + node); } }