Package net.fortytwo.ripple.model

Source Code of net.fortytwo.ripple.model.GetStatementsQuery$InvalidQueryException

package net.fortytwo.ripple.model;

import info.aduna.iteration.CloseableIteration;
import net.fortytwo.flow.Buffer;
import net.fortytwo.flow.Sink;
import net.fortytwo.ripple.RippleException;
import net.fortytwo.ripple.sail.RippleSesameValue;
import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.impl.ValueFactoryImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.XMLSchema;
import org.openrdf.sail.SailConnection;
import org.openrdf.sail.SailException;

/**
* @author Joshua Shinavier (http://fortytwo.net)
*/
public class GetStatementsQuery {
    public class InvalidQueryException extends RippleException {
        public InvalidQueryException(final String message) {
            super(message);
        }
    }

    public enum Type {SP_O, PO_S, SO_P}

    ;

    // TODO: make this into a configuration property, or find another solution
    private static final boolean STRING_LITERALS_EQUIVALENT_TO_PLAIN_LITERALS = true;

    // FIXME: this is temporary
    private static final ValueFactory VALUE_FACTORY = new ValueFactoryImpl();

    public final Resource subject;
    public final URI predicate;
    public final Value object;
    public final Resource[] contexts;
    public Type type = Type.SP_O;

    public GetStatementsQuery(final StatementPatternQuery patternQuery,
                              final ModelConnection mc) throws RippleException {
        try {
            switch (patternQuery.getPattern()) {
                case SP_O:
                    type = Type.SP_O;
                    subject = getResource(patternQuery.getSubject(), mc);
                    predicate = getURI(patternQuery.getPredicate(), mc);
                    object = null;
                    break;
                case PO_S:
                    type = Type.PO_S;
                    subject = null;
                    predicate = getURI(patternQuery.getPredicate(), mc);
                    object = getValue(patternQuery.getObject(), mc);
                    break;
                case SO_P:
                    type = Type.SO_P;
                    subject = getResource(patternQuery.getSubject(), mc);
                    predicate = null;
                    object = getValue(patternQuery.getObject(), mc);
                    break;
                default:
                    throw new InvalidQueryException("unsupported query pattern: " + patternQuery.getPattern());
            }

            RippleValue[] rippleContexts = patternQuery.getContexts();
            this.contexts = new Resource[rippleContexts.length];

            for (int i = 0; i < rippleContexts.length; i++) {
                Resource context = getResource(rippleContexts[i], mc);
//System.out.println("context is: " + context);

                // rdf:nil is a special case -- as a analysis name in Ripple, it
                // actually represents the null analysis.
                if (null != context && context.equals(RDF.NIL)) {
//                    System.out.println("    context is null");
                    context = null;
                }

                this.contexts[i] = context;
            }
        } catch (ClassCastException e) {
            throw new InvalidQueryException("value could not be cast to the appropriate Sesame type");
        }
    }

    private URI getURI(final RippleValue rv, final ModelConnection mc) throws RippleException, ClassCastException {
        return (URI) rv.toRDF(mc).sesameValue();
    }

    private Resource getResource(final RippleValue rv, final ModelConnection mc)
            throws RippleException, ClassCastException {

        RDFValue v = rv.toRDF(mc);
        return null == v ? null : (Resource) v.sesameValue();
    }

    private Value getValue(final RippleValue rv, final ModelConnection mc) throws RippleException {
        return rv.toRDF(mc).sesameValue();
    }

    public void getStatements(final SailConnection sc, final Sink<Statement> results) throws RippleException {
        getStatementsPrivate(results, sc, subject, predicate, object);

        if (STRING_LITERALS_EQUIVALENT_TO_PLAIN_LITERALS
                && null != object
                && object instanceof Literal) {
            URI datatype = ((Literal) object).getDatatype();
            if (null == datatype) {
                Literal newObj = VALUE_FACTORY.createLiteral(((Literal) object).getLabel(), XMLSchema.STRING);
                getStatementsPrivate(results, sc, subject, predicate, newObj);
            } else if (XMLSchema.STRING == datatype) {
                Literal newObj = VALUE_FACTORY.createLiteral(((Literal) object).getLabel());
                getStatementsPrivate(results, sc, subject, predicate, newObj);
            }
        }
    }

    private void getStatementsPrivate(final Sink<Statement> results,
                                      final SailConnection sc,
                                      Resource subject,
                                      URI predicate,
                                      Value object) throws RippleException {
        if (null != object && object instanceof RippleSesameValue) {
            object = ((RippleSesameValue) object).getNativeValue();
        }

        // Note: we must collect results in a buffer before putting anything
        //       into the sink, as inefficient as that is, because otherwise
        //       we might end up opening another RepositoryResult before
        //       the one below closes, which currently causes Sesame to
        //       deadlock.  Even using a separate RepositoryConnection for
        //       each RepositoryResult doesn't seem to help.
        Buffer<Statement> buffer = new Buffer<Statement>(results);
        CloseableIteration<? extends Statement, SailException> stmtIter;

//TODO: use CloseableIterationSource

        // Perform the query and collect results.
        try {
            stmtIter = sc.getStatements(subject, predicate, object, false, contexts);
//stmtIter.enableDuplicateFilter();
            try {
                while (stmtIter.hasNext()) {
                    buffer.put(stmtIter.next());
                }
            } finally {
                stmtIter.close();
            }
        } catch (SailException e) {
            throw new RippleException(e);
        }

        buffer.flush();
    }

    public void getValues(final SailConnection sc, final Sink<Value> results) throws RippleException {
        Sink<Statement> stSink = new Sink<Statement>() {
            public void put(final Statement st) throws RippleException {
                Value result;

                switch (type) {
                    case SP_O:
                        result = st.getObject();
                        break;
                    case PO_S:
                        result = st.getSubject();
                        break;
                    case SO_P:
                        result = st.getPredicate();
                        break;
                    default:
                        throw new RippleException("unhandled query type: " + type);
                }

                results.put(result);
            }
        };

        getStatements(sc, stSink);
    }
}
TOP

Related Classes of net.fortytwo.ripple.model.GetStatementsQuery$InvalidQueryException

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.