/*
* 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.client.jrdf.answer;
// Java 2 standard packages
import java.util.*;
// Log4J
import org.apache.log4j.Logger;
// JRDF
import org.jrdf.graph.*;
import org.jrdf.util.ClosableIterator;
// Local packages
import org.mulgara.client.jrdf.*;
import org.mulgara.client.jrdf.exception.*;
import org.mulgara.query.*;
import org.mulgara.server.Session;
/**
* RemoteGraphProxy implementation that retrieves it's data from an Answer.
*
* @created 2004-07-29
*
* @author <a href="mailto:robert.turner@tucanatech.com">Robert Turner</a>
*
* @version $Revision: 1.9 $
*
* @modified $Date: 2005/01/13 11:54:40 $
*
* @maintenanceAuthor $Author: newmana $
*
* @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A>
*
* @copyright ©2001 <a href="http://www.pisoftware.com/">Plugged In
* Software Pty Ltd</a>
*
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
public class RemoteAnswerGraphProxy implements RemoteGraphProxy {
/**
* Logger. This is named after the class.
*/
@SuppressWarnings("unused")
private final static Logger log = Logger.getLogger(RemoteAnswerGraphProxy.class.getName());
/** Data source */
private Answer answer = null;
/** Used to create local objects */
private GraphElementBuilder builder = null;
/** Map of Clasable iterator to be closed with this graph */
private Set<ClosableIterator<Triple>> iterators = null;
/** Indicates the Proxy has been closed */
private boolean closed = false;
/** Database Session */
private Session session = null;
/**
* Constructor.
*
*/
public RemoteAnswerGraphProxy(Answer dataSource, Session session)
throws GraphException {
super();
//cannot proceed without a valid data source
if (session == null) {
throw new GraphException("Session cannot be null.");
}
if (dataSource == null) {
throw new IllegalArgumentException("Answer cannot be null.");
}
this.session = session;
this.answer = dataSource;
this.builder = new GraphElementBuilder();
this.iterators = new HashSet<ClosableIterator<Triple>>();
}
/**
* Test the graph for the occurrence of the triple. A null value for any
* of the parts of a triple are treated as unconstrained, any values will be
* returned.
*
* @param triple The triple to find.
* @return True if the triple is found in the graph, otherwise false.
* @throws GraphException If there was an error accessing the graph.
*/
public boolean contains(Triple triple) throws GraphException {
//ensure the graph is not closed
if (this.closed) {
throw new GraphException("Graph has been closed.");
}
//do a search for the triple
ClosableIterator<Triple> iter = this.find(triple);
//if a null iterator gets returned there is a problem
if (iter == null) {
throw new GraphException("find(Triple) returned null ClosableIterator.");
}
return iter.hasNext();
}
/**
* Returns an iterator to a set of statements that match a given subject,
* predicate and object. A null value for any of the parts of a triple are
* treated as unconstrained, any values will be returned.
*
* @param triple The triple to find.
* @throws GraphException If there was an error accessing the graph.
*/
public ClosableIterator<Triple> find(Triple triple) throws GraphException {
//ensure the graph is not closed
if (this.closed) {
throw new GraphException("Graph has been closed.");
}
//create a closable iterator using the triple as a filter
try {
return this.createClosableIterator(triple, this.answer);
} catch (JRDFClientException clientException) {
throw new GraphException("Could not create new ClosableIterator.",
clientException);
}
}
/**
* Not supported.
*
* @param triples The triple iterator.
* @throws GraphExcepotion If the statements can't be made.
*/
public void add(Iterator<Triple> triples) throws GraphException {
throw new UnsupportedOperationException("RemoteAnswerGraphProxy does not " +
"support add(Triple). Graph is " +
"read-only.");
}
/**
* Not supported.
*
* @param triples The triple iterator.
* @throws GraphExcepotion If the statements can't be revoked.
*/
public void remove(Iterator<Triple> triples) throws GraphException {
throw new UnsupportedOperationException("RemoteAnswerGraphProxy does not " +
"support remove(Triple). Graph is " +
"read-only.");
}
/**
* Returns the node factory for the graph, or creates one.
*
* @return the node factory for the graph, or creates one.
*/
public GraphElementFactory getElementFactory() {
//ensure the graph is not closed
if (this.closed) {
throw new JRDFClientException("Graph has been closed.");
}
return this.builder;
}
/**
* Returns the number of rows in the Answer.
*
* @return the number of rows in the Answer.
*/
public long getNumberOfTriples() {
//ensure the graph is not closed
if (this.closed) {
throw new JRDFClientException("Graph has been closed.");
}
try {
return answer.getRowCount();
}
catch (TuplesException tuplesException) {
//rethrow
throw new JRDFClientException("Could not determine number of Triples.",
tuplesException);
}
}
/**
* Returns true if the answer's row cardinality is 0.
*
* @return true if the answer's row cardinality is 0.
*/
public boolean isEmpty() {
//ensure the graph is not closed
if (this.closed) {
throw new JRDFClientException("Graph has been closed.");
}
try {
//check if there are 0 rows (returns 0, 1 or N)
return (this.answer.getRowCardinality() <= 0);
} catch (TuplesException tuplesException) {
//rethrow
throw new JRDFClientException("Could not determine if Answer is empty.", tuplesException);
}
}
/**
* Closes the underlying Answer.
*
* @throws JRDFClientException
*/
public void close() throws JRDFClientException {
// try {
//only close once
if (!this.closed) {
// this.answer.close();
//close all created ClosableIterators
Iterator<ClosableIterator<Triple>> iter = this.iterators.iterator();
while (iter.hasNext()) {
iter.next().close();
}
}
this.closed = true;
// }
// catch (TuplesException tuplesException) {
//
// //re-throw
// throw new JRDFClientException("Could not close Answer", tuplesException);
// }
}
/**
* Removes the iterator from the list to be closed with the graph.
*
* @param iter Iterator
*/
public void unregister(Iterator<?> iter) {
this.iterators.remove(iter);
}
/**
* Factory method used to create an iterator for the Triples.
*
* @param triples Triple[]
* @return ClientClosableIterator
*/
public ClientClosableIterator<Triple> createClosableIterator(Triple[] triples) {
//ensure the graph is not closed
if (this.closed) {
throw new JRDFClientException("Graph has been closed.");
}
//create iterator and hold a reference to it
ClientClosableIterator<Triple> iterator = this.builder.createClosableIterator(
this, triples);
this.iterators.add(iterator);
return iterator;
}
/**
* Creates a closable iterator for the Answer, using the Triple as a Filter.
*
* @param filter Triple
* @param answer Answer
* @return ClientClosableIterator
*/
public ClientClosableIterator<Triple> createClosableIterator(Triple filter,
Answer answer) throws JRDFClientException {
//ensure the graph is not closed
if (this.closed) {
throw new JRDFClientException("Graph has been closed.");
}
//create a new iterator using a copy of the answer
ClosableAnswerIteratorProxy proxy = new ClosableAnswerIteratorProxy(this, filter,
(Answer) answer.clone());
//create iterator and hold a reference to it (for closing)
ClientClosableIterator<Triple> iterator = new ClientClosableIterator<Triple>(this, proxy);
this.iterators.add(iterator);
return iterator;
}
public Session getSession() {
return session;
}
}