Package net.fortytwo.ripple.model.impl.sesame

Source Code of net.fortytwo.ripple.model.impl.sesame.SesameList

package net.fortytwo.ripple.model.impl.sesame;

import net.fortytwo.flow.Collector;
import net.fortytwo.flow.Sink;
import net.fortytwo.flow.Source;
import net.fortytwo.ripple.ListNode;
import net.fortytwo.ripple.Ripple;
import net.fortytwo.ripple.RippleException;
import net.fortytwo.ripple.model.ModelConnection;
import net.fortytwo.ripple.model.Operator;
import net.fortytwo.ripple.model.RDFValue;
import net.fortytwo.ripple.model.RippleList;
import net.fortytwo.ripple.model.RippleValue;
import net.fortytwo.ripple.model.StackMapping;
import net.fortytwo.ripple.model.StatementPatternQuery;
import net.fortytwo.ripple.util.ModelConnectionHelper;
import org.openrdf.model.Value;
import org.openrdf.model.vocabulary.RDF;

import java.util.HashMap;
import java.util.Map;

/**
* @author Joshua Shinavier (http://fortytwo.net)
*/
public class SesameList extends RippleList {
    private static final RDFValue RDF_FIRST = new RDFValue(RDF.FIRST);
    private static final RDFValue RDF_REST = new RDFValue(RDF.REST);

    private static final RippleList NIL = new SesameList();

    private static Map<Value, Source<RippleList>> nativeLists = new HashMap<Value, Source<RippleList>>();
    private static Boolean memoize;

    private RDFValue rdfEquivalent;

    public static RippleList nilList() {
        return NIL;
    }

    public SesameList(final RippleValue first) {
        super(first, NIL);
    }

    public SesameList(final RippleValue first,
                      final RippleList rest) {
        super(first, rest);
    }

    // FIXME: this is temporary
    private SesameList() {
        super(null, null);
        // Note: this is a trick to avoid null pointer exceptions in the list memoizer.
        first = this;

        rdfEquivalent = new RDFValue(RDF.NIL);
    }

    public boolean isNil() {
        return null == rest;
    }

    public RippleList push(final RippleValue first) throws RippleException {
        return new SesameList(first, this);
    }

    public RippleList invert() {
        ListNode<RippleValue> in = this;
        RippleList out = NIL;

        while (NIL != in) {
            out = new SesameList(in.getFirst(), out);
            in = in.getRest();
        }

        return out;
    }

    public StackMapping getMapping() {
        return null;
    }

    public RDFValue toRDF(final ModelConnection mc)
            throws RippleException {
        if (null == rdfEquivalent) {
            rdfEquivalent = new ModelConnectionHelper(mc).createRandomURI();
        }

        return rdfEquivalent;
    }

    public RippleList concat(final RippleList tail) {
        return (NIL == this)
                ? tail
                : new SesameList(this.getFirst(), concat(this.getRest(), tail));
    }

    public static RippleList concat(final RippleList head, final RippleList tail) {
        return (NIL == head)
                ? tail
                : new SesameList(head.getFirst(), concat(head.getRest(), tail));
    }

    public static void from(final RippleValue v,
                            final Sink<RippleList> sink,
                            final ModelConnection mc)
            throws RippleException {
        if (null == memoize) {
            memoize = Ripple.getConfiguration().getBoolean(Ripple.MEMOIZE_LISTS_FROM_RDF);
        }

        // If already a list...
        if (v instanceof RippleList) {
            sink.put((RippleList) v);
        }

        // If the argument is an RDF value, try to convert it to a native list.
        else if (v instanceof RDFValue) {
            if (memoize) {
//System.out.println("looking for source for list: " + v);
                Value rdfVal = ((RDFValue) v).toRDF(mc).sesameValue();
                Source<RippleList> source = nativeLists.get(rdfVal);
                if (null == source) {
                    Collector<RippleList> coll = new Collector<RippleList>();

                    listsFromRdf(v, coll, mc);

                    source = coll;
                    nativeLists.put(rdfVal, source);
                }
//else System.out.println("   found source for list");

                source.writeTo(sink);
            } else {
                listsFromRdf(v, sink, mc);
            }
        }

        // Towards a more general notion of lists
        else {
            createConceptualList(v, sink, mc);
        }

        /*
          // Otherwise, fail.
          else
          {
              throw new RippleException( "expecting " + RippleList.class + ", found " + v );
          }*/
    }

    // TODO: find a better name
    private static void createConceptualList(final RippleValue head,
                                             final Sink<RippleList> sink,
                                             final ModelConnection mc)
            throws RippleException {
        /*
          Sink<Operator> opSink = new Sink<Operator>()
          {
              public void put( final Operator op )
                  throws RippleException
              {
                  sink.put( mc.list( op ) );
              }
          };
 
          Operator.createOperator( head, opSink, mc );
          */

        sink.put(new SesameList(Operator.OP).push(head));
    }

    // TODO: extend circular lists and other convergent structures
    private static void listsFromRdf(final RippleValue head,
                                     final Sink<RippleList> sink,
                                     final ModelConnection mc)
            throws RippleException {
        if (head.toRDF(mc).sesameValue().equals(RDF.NIL)) {
            sink.put(NIL);
        } else {
            final Collector<RippleValue> firstValues = new Collector<RippleValue>();

            final Sink<RippleList> restSink = new Sink<RippleList>() {
                public void put(final RippleList rest) throws RippleException {
                    Sink<RippleValue> firstSink = new Sink<RippleValue>() {
                        public void put(final RippleValue first) throws RippleException {
                            SesameList list = new SesameList(first, rest);
                            list.rdfEquivalent = head.toRDF(mc);
                            sink.put(list);
                        }
                    };

                    firstValues.writeTo(firstSink);
                }
            };

            Sink<RippleValue> rdfRestSink = new Sink<RippleValue>() {
                public void put(final RippleValue rest) throws RippleException {
                    // Recurse.
                    listsFromRdf(rest, restSink, mc);
                }
            };

            /*
               Sink<RdfValue> rdfFirstSink = new Sink<RdfValue>()
               {
                   public void put( final RdfValue first ) throws RippleException
                   {
                       // Note: it might be more efficient to use ModelBridge only
                       //       lazily, binding RDF to generic RippleValues on an
                       //       as-needed basis.  However, for now there is no better
                       //       place to do this when we're coming from an rdf:List.
                       //       Consider a list containing operators.
                       firstValues.put( mc.getModel().getBridge().get( first ) );
                   }
               };*/

            multiply(mc, head, RDF_FIRST, firstValues);

            if (firstValues.size() > 0 || head.toRDF(mc).sesameValue().equals(RDF.NIL)) {
                multiply(mc, head, RDF_REST, rdfRestSink);
            } else {
                createConceptualList(head, sink, mc);
            }
        }
    }

    private static void multiply(final ModelConnection mc,
                                 final RippleValue subj,
                                 final RippleValue pred,
                                 final Sink<RippleValue> sink) throws RippleException {
        StatementPatternQuery query = new StatementPatternQuery(subj, pred, null);
        mc.query(query, sink, false);
    }

    public void setRDF(final RDFValue id) {
        rdfEquivalent = id;
    }
}
TOP

Related Classes of net.fortytwo.ripple.model.impl.sesame.SesameList

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.