Package org.fcrepo.server.resourceIndex

Source Code of org.fcrepo.server.resourceIndex.ResourceIndexImpl

/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.server.resourceIndex;

import java.io.IOException;
import java.io.OutputStream;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jrdf.graph.GraphElementFactory;
import org.jrdf.graph.GraphElementFactoryException;
import org.jrdf.graph.Literal;
import org.jrdf.graph.Node;
import org.jrdf.graph.ObjectNode;
import org.jrdf.graph.PredicateNode;
import org.jrdf.graph.SubjectNode;
import org.jrdf.graph.Triple;
import org.jrdf.graph.URIReference;

import org.trippi.FlushErrorHandler;
import org.trippi.RDFFormat;
import org.trippi.TripleIterator;
import org.trippi.TripleUpdate;
import org.trippi.TriplestoreConnector;
import org.trippi.TriplestoreWriter;
import org.trippi.TrippiException;
import org.trippi.TupleIterator;

import org.fcrepo.server.errors.ResourceIndexException;
import org.fcrepo.server.storage.DOReader;


/**
* Implementation of the <code>ResourceIndex</code>.
*
* @author Chris Wilper
*/
public class ResourceIndexImpl
        implements ResourceIndex {

    /** Interface to the underlying triplestore. */
    private final TriplestoreConnector _connector;

    /** Writer for the underlying triplestore. */
    private final TriplestoreWriter _writer;

    /** The TripleGenerator this instance will use. */
    private final TripleGenerator _generator;

    /** The current index level. */
    private final int _indexLevel;

    /**
     * Whether triples should be flushed to storage before returning from each
     * object modification method.
     */
    private final boolean _syncUpdates;

    ////////////////////
    // Initialization //
    ////////////////////

    public ResourceIndexImpl(TriplestoreConnector connector,
                             TripleGenerator generator,
                             int indexLevel,
                             boolean syncUpdates) {
        _connector = connector;
        _writer = _connector.getWriter();
        _generator = generator;
        _indexLevel = indexLevel;
        _syncUpdates = syncUpdates;
    }

    ///////////////////////////
    // ResourceIndex methods //
    ///////////////////////////

    /**
     * {@inheritDoc}
     */
    public int getIndexLevel() {
        return _indexLevel;
    }

    /**
     * {@inheritDoc}
     */
    public void addObject(DOReader reader) throws ResourceIndexException {
        if (_indexLevel > INDEX_LEVEL_OFF) {
            updateTriples(_generator.getTriplesForObject(reader), false);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void modifyObject(DOReader oldReader, DOReader newReader)
            throws ResourceIndexException {
        if (_indexLevel > INDEX_LEVEL_OFF) {
            updateTripleDiffs(_generator.getTriplesForObject(oldReader),
                              _generator.getTriplesForObject(newReader));
        }
    }

    /**
     * {@inheritDoc}
     */
    public void deleteObject(DOReader oldReader) throws ResourceIndexException {
        if (_indexLevel > INDEX_LEVEL_OFF) {
            updateTriples(_generator.getTriplesForObject(oldReader), true);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void export(OutputStream out, RDFFormat format)
            throws ResourceIndexException {
        try {
            TripleIterator it = _writer.findTriples(null, null, null, 0);
            it.setAliasMap(_writer.getAliasMap());
            it.toStream(out, format);
        } catch (TrippiException e) {
            throw new ResourceIndexException("Unable to export RI", e);
        }
    }

    /////////////////////
    // Private Methods //
    /////////////////////

    /**
     * Applies the given adds or deletes to the triplestore. If _syncUpdates is
     * true, changes will be flushed before returning.
     */
    private void updateTriples(Set<Triple> set, boolean delete)
            throws ResourceIndexException {
        try {
            if (delete) {
                _writer.delete(getTripleIterator(set), _syncUpdates);
            } else {
                _writer.add(getTripleIterator(set), _syncUpdates);
            }
        } catch (Exception e) {
            throw new ResourceIndexException("Error updating triples", e);
        }
    }

    /**
     * Computes the difference between the given sets and applies the
     * appropriate deletes and adds to the triplestore. If _syncUpdates is true,
     * changes will be flushed before returning.
     */
    private void updateTripleDiffs(Set<Triple> existing, Set<Triple> desired)
            throws ResourceIndexException {

        // Delete any existing triples that are no longer desired,
        // leaving the ones we want in place
        HashSet<Triple> obsoleteTriples = new HashSet<Triple>(existing);
        obsoleteTriples.removeAll(desired);
        updateTriples(obsoleteTriples, true);

        // Add only new desired triples
        HashSet<Triple> newTriples = new HashSet<Triple>(desired);
        newTriples.removeAll(existing);
        updateTriples(newTriples, false);

    }

    /**
     * Gets a Trippi TripleIterator for the given set.
     */
    private TripleIterator getTripleIterator(final Set<Triple> set) {
        return new TripleIterator() {

            private final Iterator<Triple> _iter = set.iterator();

            @Override
            public boolean hasNext() {
                return _iter.hasNext();
            }

            @Override
            public Triple next() {
                return getLocalizedTriple(_iter.next());
            }

            @Override
            public void close() {
            }
        };
    }
   
    /**
     * Gets a Triple appropriate for writing to the store.
     */
    private Triple getLocalizedTriple(Triple triple) {
        try {
            return _connector.getElementFactory().createTriple(
                    getLocalizedResource(triple.getSubject()),
                    getLocalizedResource(triple.getPredicate()),
                    getLocalizedObject(triple.getObject()));
        } catch (GraphElementFactoryException e) {
            throw new RuntimeException("Error localizing triple", e);
        }
    }

    /**
     * Gets a localized URIReference based on the given Node.
     */
    private URIReference getLocalizedResource(Node n)
            throws GraphElementFactoryException {
        if (n instanceof URIReference) {
            URIReference u = (URIReference) n;
            return _connector.getElementFactory().createResource(u.getURI());
        } else {
            throw new RuntimeException("Error localizing triple; "
                    + n.getClass().getName() + " is not a URIReference");
        }
    }

    /**
     * Gets a localized URIReference or Literal based on the given Node.
     */
    private ObjectNode getLocalizedObject(Node n)
            throws GraphElementFactoryException {
        if (n instanceof URIReference) {
            return getLocalizedResource(n);
        } else if (n instanceof Literal) {
            Literal l = (Literal) n;
            GraphElementFactory elementFactory = _connector.getElementFactory();
            if (l.getDatatypeURI() != null) {
                return elementFactory.createLiteral(l.getLexicalForm(),
                                                    l.getDatatypeURI());
            } else if (l.getLanguage() != null) {
                return elementFactory.createLiteral(l.getLexicalForm(),
                                                    l.getLanguage());
            } else {
                return elementFactory.createLiteral(l.getLexicalForm());
            }
        } else {
            throw new RuntimeException("Error localizing triple; "
                    + n.getClass().getName() + " is not a URIReference "
                    + "or a Literal");
        }
    }

    ///////////////////////////////
    // TriplestoreReader methods //
    ///////////////////////////////

    /**
     * {@inheritDoc}
     */
    public void setAliasMap(Map<String, String> aliasToPrefix)
            throws TrippiException {
        _writer.setAliasMap(aliasToPrefix);
    }

    /**
     * {@inheritDoc}
     */
    public Map<String, String> getAliasMap() throws TrippiException {
        return _writer.getAliasMap();
    }

    /**
     * {@inheritDoc}
     */
    public TupleIterator findTuples(String queryLang,
                                    String tupleQuery,
                                    int limit,
                                    boolean distinct) throws TrippiException {
        return _writer.findTuples(queryLang, tupleQuery, limit, distinct);
    }

    /**
     * {@inheritDoc}
     */
    public int countTuples(String queryLang,
                           String tupleQuery,
                           int limit,
                           boolean distinct) throws TrippiException {
        return _writer.countTuples(queryLang, tupleQuery, limit, distinct);
    }

    /**
     * {@inheritDoc}
     */
    public TripleIterator findTriples(String queryLang,
                                      String tripleQuery,
                                      int limit,
                                      boolean distinct) throws TrippiException {
        return _writer.findTriples(queryLang, tripleQuery, limit, distinct);
    }

    /**
     * {@inheritDoc}
     */
    public int countTriples(String queryLang,
                            String tripleQuery,
                            int limit,
                            boolean distinct) throws TrippiException {
        return _writer.countTriples(queryLang, tripleQuery, limit, distinct);
    }

    /**
     * {@inheritDoc}
     */
    public TripleIterator findTriples(SubjectNode subject,
                                      PredicateNode predicate,
                                      ObjectNode object,
                                      int limit) throws TrippiException {
        return _writer.findTriples(subject, predicate, object, limit);
    }

    /**
     * {@inheritDoc}
     */
    public int countTriples(SubjectNode subject,
                            PredicateNode predicate,
                            ObjectNode object,
                            int limit) throws TrippiException {
        return _writer.countTriples(subject, predicate, object, limit);
    }

    /**
     * {@inheritDoc}
     */
    public TripleIterator findTriples(String queryLang,
                                      String tupleQuery,
                                      String tripleTemplate,
                                      int limit,
                                      boolean distinct) throws TrippiException {
        return _writer.findTriples(queryLang,
                                   tupleQuery,
                                   tripleTemplate,
                                   limit,
                                   distinct);
    }

    /**
     * {@inheritDoc}
     */
    public int countTriples(String queryLang,
                            String tupleQuery,
                            String tripleTemplate,
                            int limit,
                            boolean distinct) throws TrippiException {
        return _writer.countTriples(queryLang,
                                    tupleQuery,
                                    tripleTemplate,
                                    limit,
                                    distinct);
    }

    /**
     * {@inheritDoc}
     */
    public String[] listTupleLanguages() {
        return _writer.listTupleLanguages();
    }

    /**
     * {@inheritDoc}
     */
    public String[] listTripleLanguages() {
        return _writer.listTripleLanguages();
    }

    /**
     * {@inheritDoc}
     */
    public void close() throws TrippiException {
        _connector.close();
    }

    ///////////////////////////////
    // TriplestoreWriter methods //
    ///////////////////////////////

    /**
     * {@inheritDoc}
     */
    public void add(List<Triple> triples, boolean flush) throws IOException,
            TrippiException {
        _writer.add(triples, flush);
    }

    /**
     * {@inheritDoc}
     */
    public void add(TripleIterator triples, boolean flush) throws IOException,
            TrippiException {
        _writer.add(triples, flush);
    }

    /**
     * {@inheritDoc}
     */
    public void add(Triple triple, boolean flush) throws IOException,
            TrippiException {
        _writer.add(triple, flush);
    }

    /**
     * {@inheritDoc}
     */
    public void delete(List<Triple> triples, boolean flush) throws IOException,
            TrippiException {
        _writer.delete(triples, flush);
    }

    /**
     * {@inheritDoc}
     */
    public void delete(TripleIterator triples, boolean flush)
            throws IOException, TrippiException {
        _writer.delete(triples, flush);
    }

    /**
     * {@inheritDoc}
     */
    public void delete(Triple triple, boolean flush) throws IOException,
            TrippiException {
        _writer.delete(triple, flush);
    }

    /**
     * {@inheritDoc}
     */
    public void flushBuffer() throws IOException, TrippiException {
        _writer.flushBuffer();
    }

    /**
     * {@inheritDoc}
     */
    public void setFlushErrorHandler(FlushErrorHandler h) {
        _writer.setFlushErrorHandler(h);
    }

    /**
     * {@inheritDoc}
     */
    public int getBufferSize() {
        return _writer.getBufferSize();
    }

    /**
     * {@inheritDoc}
     */
    public List<TripleUpdate> findBufferedUpdates(SubjectNode subject,
                                                  PredicateNode predicate,
                                                  ObjectNode object,
                                                  int updateType) {
        return _writer.findBufferedUpdates(subject,
                                           predicate,
                                           object,
                                           updateType);
    }

}
TOP

Related Classes of org.fcrepo.server.resourceIndex.ResourceIndexImpl

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.