Package org.openrdf.model.impl

Source Code of org.openrdf.model.impl.LinkedHashModel$ModelNode

/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 2008.
*
* Licensed under the Aduna BSD-style license.
*/
package org.openrdf.model.impl;

import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableSet;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

import info.aduna.collections.iterators.FilterIterator;

import org.openrdf.OpenRDFUtil;
import org.openrdf.model.Literal;
import org.openrdf.model.Model;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.util.ModelException;
import org.openrdf.model.util.ModelUtil;

/**
* @author James Leigh
*/
@SuppressWarnings("unchecked")
public class LinkedHashModel extends AbstractSet<Statement> implements Model {

  private static final long serialVersionUID = -9161104123818983614L;

  static final Resource[] NULL_CTX = new Resource[] { null };

  Map<String, String> namespaces = new LinkedHashMap<String, String>();

  transient Map<Value, ModelNode> values;

  transient Set<ModelStatement> statements;

  public LinkedHashModel() {
    super();
    values = new HashMap<Value, ModelNode>();
    statements = new LinkedHashSet<ModelStatement>();
  }

  public LinkedHashModel(Collection<? extends Statement> c) {
    super();
    values = new HashMap<Value, ModelNode>(c.size() * 2);
    statements = new LinkedHashSet<ModelStatement>(c.size());
    addAll(c);
  }

  public LinkedHashModel(int size) {
    super();
    values = new HashMap<Value, ModelNode>(size * 2);
    statements = new LinkedHashSet<ModelStatement>(size);
  }

  public LinkedHashModel(Map<String, String> namespaces, Collection<? extends Statement> c) {
    this(c);
    this.namespaces.putAll(namespaces);
  }

  public LinkedHashModel(Map<String, String> namespaces) {
    this();
    this.namespaces.putAll(namespaces);
  }

  public LinkedHashModel(Map<String, String> namespaces, int size) {
    this(size);
    this.namespaces.putAll(namespaces);
  }

  public String getNamespace(String prefix) {
    return namespaces.get(prefix);
  }

  public Map<String, String> getNamespaces() {
    return namespaces;
  }

  public String setNamespace(String prefix, String name) {
    return namespaces.put(prefix, name);
  }

  public void removeNamespace(String prefix) {
    namespaces.remove(prefix);
  }

  @Override
  public int size() {
    return statements.size();
  }

  @Override
  public boolean add(Statement st) {
    return add(st.getSubject(), st.getPredicate(), st.getObject(), st.getContext());
  }

  public boolean add(Resource subj, URI pred, Value obj, Resource... contexts) {
    Resource[] ctxs = OpenRDFUtil.notNull(contexts);
    if (ctxs.length == 0) {
      ctxs = NULL_CTX;
    }
    boolean changed = false;
    for (Resource ctx : ctxs) {
      ModelNode<Resource> s = asNode(subj);
      ModelNode<URI> p = asNode(pred);
      ModelNode<Value> o = asNode(obj);
      ModelNode<Resource> c = asNode(ctx);
      ModelStatement st = new ModelStatement(s, p, o, c);
      changed |= addModelStatement(st);
    }
    return changed;
  }

  @Override
  public void clear() {
    values.clear();
    statements.clear();
  }

  @Override
  public boolean remove(Object o) {
    if (o instanceof Statement) {
      Iterator iter = find((Statement)o);
      if (iter.hasNext()) {
        iter.next();
        iter.remove();
        return true;
      }
    }
    return false;
  }

  @Override
  public boolean contains(Object o) {
    if (o instanceof Statement) {
      return find((Statement)o).hasNext();
    }
    return false;
  }

  @Override
  public Iterator iterator() {
    return match(null, null, null);
  }

  public boolean contains(Resource subj, URI pred, Value obj, Resource... contexts) {
    return match(subj, pred, obj, contexts).hasNext();
  }

  public boolean remove(Resource subj, URI pred, Value obj, Resource... contexts) {
    Iterator iter = match(subj, pred, obj, contexts);
    if (!iter.hasNext()) {
      return false;
    }
    while (iter.hasNext()) {
      iter.next();
      iter.remove();
    }
    return true;
  }

  public boolean clear(Resource... contexts) {
    return remove(null, null, null, contexts);
  }

  public Model filter(Resource subj, URI pred, Value obj, Resource... contexts) {
    return new FilteredModel(subj, pred, obj, contexts);
  }

  public Set<Resource> subjects() {
    return subjects(null, null);
  }

  public Set<URI> predicates() {
    return predicates(null, null);
  }

  public Set<Value> objects() {
    return objects(null, null);
  }

  public Set<Resource> contexts() {
    return contexts(null, null, null);
  }

  public Value objectValue()
    throws ModelException
  {
    Iterator<Value> iter = objects().iterator();
    if (iter.hasNext()) {
      Value obj = iter.next();
      if (iter.hasNext()) {
        throw new ModelException();
      }
      return obj;
    }
    return null;
  }

  public Literal objectLiteral()
    throws ModelException
  {
    Value obj = objectValue();
    if (obj == null) {
      return null;
    }
    if (obj instanceof Literal) {
      return (Literal)obj;
    }
    throw new ModelException();
  }

  public Resource objectResource()
    throws ModelException
  {
    Value obj = objectValue();
    if (obj == null) {
      return null;
    }
    if (obj instanceof Resource) {
      return (Resource)obj;
    }
    throw new ModelException();
  }

  public URI objectURI()
    throws ModelException
  {
    Value obj = objectValue();
    if (obj == null) {
      return null;
    }
    if (obj instanceof URI) {
      return (URI)obj;
    }
    throw new ModelException();
  }

  public String objectString()
    throws ModelException
  {
    Value obj = objectValue();
    if (obj == null) {
      return null;
    }
    return obj.stringValue();
  }

  @Override
  public int hashCode() {
    return size();
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o instanceof Model) {
      Model model = (Model)o;
      return ModelUtil.equals(this, model);
    }
    return false;
  }

  Set<Resource> contexts(final Resource subj, final URI pred, final Value obj) {
    return new ValueSet<Resource>() {

      @Override
      public boolean contains(Object o) {
        if (o instanceof Resource || o == null) {
          return LinkedHashModel.this.contains(subj, pred, obj, (Resource)o);
        }
        return false;
      }

      @Override
      public boolean remove(Object o) {
        if (o instanceof Resource || o == null) {
          return LinkedHashModel.this.remove(subj, pred, obj, (Resource)o);
        }
        return false;
      }

      @Override
      public boolean add(Resource ctx) {
        if (subj == null || pred == null || obj == null) {
          throw new UnsupportedOperationException("Incomplete statement");
        }
        if (contains(ctx)) {
          return false;
        }
        return LinkedHashModel.this.add(subj, pred, obj, ctx);
      }

      @Override
      public void clear() {
        LinkedHashModel.this.remove(subj, pred, obj);
      }

      @Override
      protected ModelIterator statementIterator() {
        return match(subj, pred, obj);
      }

      @Override
      protected ModelNode<Resource> node(ModelStatement st) {
        return st.ctx;
      }

      @Override
      protected Set<ModelStatement> set(ModelNode<Resource> node) {
        return node.contexts;
      }
    };
  }

  Set<Value> objects(final Resource subj, final URI pred, final Resource... contexts) {
    return new ValueSet<Value>() {

      @Override
      public boolean contains(Object o) {
        if (o instanceof Value) {
          return LinkedHashModel.this.contains(subj, pred, (Value)o, contexts);
        }
        return false;
      }

      @Override
      public boolean remove(Object o) {
        if (o instanceof Value) {
          return LinkedHashModel.this.remove(subj, pred, (Value)o, contexts);
        }
        return false;
      }

      @Override
      public boolean add(Value obj) {
        if (subj == null || pred == null) {
          throw new UnsupportedOperationException("Incomplete statement");
        }
        if (contains(obj)) {
          return false;
        }
        return LinkedHashModel.this.add(subj, pred, obj, contexts);
      }

      @Override
      public void clear() {
        LinkedHashModel.this.remove(subj, pred, null, contexts);
      }

      @Override
      protected ModelIterator statementIterator() {
        return match(subj, pred, null, contexts);
      }

      @Override
      protected ModelNode<Value> node(ModelStatement st) {
        return st.obj;
      }

      @Override
      protected Set<ModelStatement> set(ModelNode<Value> node) {
        return node.objects;
      }
    };
  }

  Set<URI> predicates(final Resource subj, final Value obj, final Resource... contexts) {
    return new ValueSet<URI>() {

      @Override
      public boolean contains(Object o) {
        if (o instanceof URI) {
          return LinkedHashModel.this.contains(subj, (URI)o, obj, contexts);
        }
        return false;
      }

      @Override
      public boolean remove(Object o) {
        if (o instanceof URI) {
          return LinkedHashModel.this.remove(subj, (URI)o, obj, contexts);
        }
        return false;
      }

      @Override
      public boolean add(URI pred) {
        if (subj == null || obj == null) {
          throw new UnsupportedOperationException("Incomplete statement");
        }
        if (contains(pred)) {
          return false;
        }
        return LinkedHashModel.this.add(subj, pred, obj, contexts);
      }

      @Override
      public void clear() {
        LinkedHashModel.this.remove(subj, null, obj, contexts);
      }

      @Override
      protected ModelIterator statementIterator() {
        return match(subj, null, obj, contexts);
      }

      @Override
      protected ModelNode<URI> node(ModelStatement st) {
        return st.pred;
      }

      @Override
      protected Set<ModelStatement> set(ModelNode<URI> node) {
        return node.predicates;
      }
    };
  }

  Set<Resource> subjects(final URI pred, final Value obj, final Resource... contexts) {
    return new ValueSet<Resource>() {

      @Override
      public boolean contains(Object o) {
        if (o instanceof Resource) {
          return LinkedHashModel.this.contains((Resource)o, pred, obj, contexts);
        }
        return false;
      }

      @Override
      public boolean remove(Object o) {
        if (o instanceof Resource) {
          return LinkedHashModel.this.remove((Resource)o, pred, obj, contexts);
        }
        return false;
      }

      @Override
      public boolean add(Resource subj) {
        if (pred == null || obj == null) {
          throw new UnsupportedOperationException("Incomplete statement");
        }
        if (contains(subj)) {
          return false;
        }
        return LinkedHashModel.this.add(subj, pred, obj, contexts);
      }

      @Override
      public void clear() {
        LinkedHashModel.this.remove(null, pred, obj, contexts);
      }

      @Override
      protected ModelIterator statementIterator() {
        return match(null, pred, obj, contexts);
      }

      @Override
      protected ModelNode<Resource> node(ModelStatement st) {
        return st.subj;
      }

      @Override
      protected Set<ModelStatement> set(ModelNode<Resource> node) {
        return node.subjects;
      }
    };
  }

  ModelIterator match(Resource subj, URI pred, Value obj, Resource... contexts) {
    assert contexts != null;
    Set<ModelStatement> s = null;
    Set<ModelStatement> p = null;
    Set<ModelStatement> o = null;
    if (subj != null) {
      if (!values.containsKey(subj)) {
        return emptyModelIterator();
      }
      s = values.get(subj).subjects;
    }
    if (pred != null) {
      if (!values.containsKey(pred)) {
        return emptyModelIterator();
      }
      p = values.get(pred).predicates;
    }
    if (obj != null) {
      if (!values.containsKey(obj)) {
        return emptyModelIterator();
      }
      o = values.get(obj).objects;
    }
    Set<ModelStatement> set;
    contexts = OpenRDFUtil.notNull(contexts);
    if (contexts.length == 1) {
      if (!values.containsKey(contexts[0])) {
        return emptyModelIterator();
      }
      Set<ModelStatement> c = values.get(contexts[0]).contexts;
      set = smallest(statements, s, p, o, c);
    }
    else {
      set = smallest(statements, s, p, o);
    }
    Iterator<ModelStatement> it = set.iterator();
    Iterator<ModelStatement> iter;
    iter = new PatternIterator(it, subj, pred, obj, contexts);
    return new ModelIterator(iter, set);
  }

  boolean matches(Statement st, Resource subj, URI pred, Value obj, Resource... contexts) {
    if (subj != null && !subj.equals(st.getSubject())) {
      return false;
    }
    if (pred != null && !pred.equals(st.getPredicate())) {
      return false;
    }
    if (obj != null && !obj.equals(st.getObject())) {
      return false;
    }

    return matches(st.getContext(), contexts);
  }

  boolean matches(Resource[] stContext, Resource... contexts) {
    if (stContext != null && stContext.length > 0) {
      for (Resource c : stContext) {
        if (!matches(c, contexts)) {
          return false;
        }
      }
    }
    return true;
  }

  boolean matches(Resource stContext, Resource... contexts) {
    if (contexts != null && contexts.length == 0) {
      // Any context matches
      return true;
    }
    else {
      // Accept if one of the contexts from the pattern matches
      for (Resource context : OpenRDFUtil.notNull(contexts)) {
        if (context == null && stContext == null) {
          return true;
        }
        if (context != null && context.equals(stContext)) {
          return true;
        }
      }

      return false;
    }
  }

  Model emptyModel = new EmptyModel();

  Model emptyModel() {
    return emptyModel;
  }

  ModelIterator emptyModelIterator() {
    Set<ModelStatement> set = Collections.emptySet();
    return new ModelIterator(set.iterator(), set);
  }

  class EmptyModel extends AbstractSet<Statement> implements Model {

    private static final long serialVersionUID = 3123007631452759092L;

    private Set<Statement> emptySet = Collections.emptySet();

    public String getNamespace(String prefix) {
      return namespaces.get(prefix);
    }

    public Map<String, String> getNamespaces() {
      return namespaces;
    }

    public String setNamespace(String prefix, String name) {
      return namespaces.put(prefix, name);
    }

    public void removeNamespace(String prefix) {
      namespaces.remove(prefix);
    }

    @Override
    public Iterator<Statement> iterator() {
      return emptySet.iterator();
    }

    @Override
    public int size() {
      return 0;
    }

    @Override
    public boolean add(Statement e) {
      throw new UnsupportedOperationException("All statements are filtered out of view");
    }

    public boolean add(Resource subj, URI pred, Value obj, Resource... contexts) {
      throw new UnsupportedOperationException("All statements are filtered out of view");
    }

    public boolean clear(Resource... context) {
      return false;
    }

    public boolean contains(Resource subj, URI pred, Value obj, Resource... contexts) {
      return false;
    }

    public Set<Resource> contexts() {
      return Collections.emptySet();
    }

    public Model filter(Resource subj, URI pred, Value obj, Resource... contexts) {
      return emptyModel;
    }

    public Set<Value> objects() {
      return Collections.emptySet();
    }

    public Set<URI> predicates() {
      return Collections.emptySet();
    }

    public boolean remove(Resource subj, URI pred, Value obj, Resource... contexts) {
      return false;
    }

    public Set<Resource> subjects() {
      return Collections.emptySet();
    }

    public Literal objectLiteral() {
      return null;
    }

    public Value objectValue() {
      return null;
    }

    public Resource objectResource() {
      return null;
    }

    public URI objectURI() {
      return null;
    }

    public String objectString()
      throws ModelException
    {
      return null;
    }

    @Override
    public int hashCode() {
      return size();
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o instanceof Model) {
        Model model = (Model)o;
        return model.isEmpty();
      }
      return false;
    }

  }

  class FilteredModel extends AbstractSet<Statement> implements Model {

    private static final long serialVersionUID = -2353344619836326934L;

    private Resource subj;

    private URI pred;

    private Value obj;

    private Resource[] contexts;

    public FilteredModel(Resource subj, URI pred, Value obj, Resource... contexts) {
      this.subj = subj;
      this.pred = pred;
      this.obj = obj;
      this.contexts = OpenRDFUtil.notNull(contexts);
    }

    public String getNamespace(String prefix) {
      return namespaces.get(prefix);
    }

    public Map<String, String> getNamespaces() {
      return namespaces;
    }

    public String setNamespace(String prefix, String name) {
      return namespaces.put(prefix, name);
    }

    public void removeNamespace(String prefix) {
      namespaces.remove(prefix);
    }

    @Override
    public Iterator<Statement> iterator() {
      final ModelIterator iter = statementIterator();
      return new Iterator<Statement>() {

        private ModelStatement current;

        private ModelStatement next;

        public boolean hasNext() {
          if (next == null && iter.hasNext()) {
            next = iter.next();
          }
          return next != null;
        }

        public ModelStatement next() {
          if (next == null) {
            next = iter.next();
          }
          current = next;
          next = null;
          return current;
        }

        public void remove() {
          iter.remove();
        }
      };
    }

    @Override
    public int size() {
      int size = 0;
      Iterator<ModelStatement> iter = statementIterator();
      while (iter.hasNext()) {
        size++;
        iter.next();
      }
      return size;
    }

    @Override
    public boolean contains(Object o) {
      if (o instanceof Statement) {
        Statement st = (Statement)o;
        if (accept(st)) {
          return LinkedHashModel.this.contains(o);
        }
      }
      return false;
    }

    @Override
    public boolean add(Statement st) {
      if (accept(st)) {
        return LinkedHashModel.this.add(st);
      }
      throw new IllegalArgumentException("Statement is filtered out of view: " + st);
    }

    public boolean add(Resource s, URI p, Value o, Resource... c) {
      if (!accept(s, p, o, c)) {
        throw new IllegalArgumentException("Statement is filtered out of view");
      }
      if (s == null) {
        s = subj;
      }
      if (p == null) {
        p = pred;
      }
      if (o == null) {
        o = obj;
      }
      if (c != null && c.length == 0) {
        c = contexts;
      }
      return LinkedHashModel.this.add(s, p, o, c);
    }

    @Override
    public void clear() {
      LinkedHashModel.this.remove(subj, pred, obj, contexts);
    }

    public boolean clear(Resource... c) {
      c = OpenRDFUtil.notNull(c);
      if (c.length == 0) {
        return remove(subj, pred, obj, contexts);
      }
      else if (matches(c, contexts)) {
        return LinkedHashModel.this.remove(subj, pred, obj, c);
      }
      else {
        return false;
      }
    }

    public boolean remove(Resource s, URI p, Value o, Resource... c) {
      if (!accept(s, p, o, c)) {
        return false;
      }
      if (s == null) {
        s = subj;
      }
      if (p == null) {
        p = pred;
      }
      if (o == null) {
        o = obj;
      }
      if (c != null && c.length == 0) {
        c = contexts;
      }
      return LinkedHashModel.this.remove(s, p, o, c);
    }

    public boolean contains(Resource s, URI p, Value o, Resource... c) {
      if (!accept(s, p, o, c)) {
        return false;
      }
      if (s == null) {
        s = subj;
      }
      if (p == null) {
        p = pred;
      }
      if (o == null) {
        o = obj;
      }
      if (c != null && c.length == 0) {
        c = contexts;
      }
      return LinkedHashModel.this.contains(s, p, o, c);
    }

    public Model filter(Resource s, URI p, Value o, Resource... c) {
      if (!accept(s, p, o, c)) {
        return emptyModel();
      }
      if (s == null) {
        s = subj;
      }
      if (p == null) {
        p = pred;
      }
      if (o == null) {
        o = obj;
      }
      if (c != null && c.length == 0) {
        c = contexts;
      }
      return LinkedHashModel.this.filter(s, p, o, c);
    }

    public Set<Resource> contexts() {
      if (contexts != null && contexts.length > 0) {
        return unmodifiableSet(new LinkedHashSet<Resource>(asList(contexts)));
      }
      return LinkedHashModel.this.contexts(subj, pred, obj);
    }

    public Set<Value> objects() {
      if (obj != null) {
        return Collections.singleton(obj);
      }
      return LinkedHashModel.this.objects(subj, pred, contexts);
    }

    public Set<URI> predicates() {
      if (pred != null) {
        return Collections.singleton(pred);
      }
      return LinkedHashModel.this.predicates(subj, obj, contexts);
    }

    public Set<Resource> subjects() {
      if (subj != null) {
        return Collections.singleton(subj);
      }
      return LinkedHashModel.this.subjects(pred, obj, contexts);
    }

    public Value objectValue()
      throws ModelException
    {
      Iterator<Value> iter = objects().iterator();
      if (iter.hasNext()) {
        Value obj = iter.next();
        if (iter.hasNext()) {
          throw new ModelException();
        }
        return obj;
      }
      return null;
    }

    public Literal objectLiteral()
      throws ModelException
    {
      Value obj = objectValue();
      if (obj == null) {
        return null;
      }
      if (obj instanceof Literal) {
        return (Literal)obj;
      }
      throw new ModelException();
    }

    public Resource objectResource()
      throws ModelException
    {
      Value obj = objectValue();
      if (obj == null) {
        return null;
      }
      if (obj instanceof Resource) {
        return (Resource)obj;
      }
      throw new ModelException();
    }

    public URI objectURI()
      throws ModelException
    {
      Value obj = objectValue();
      if (obj == null) {
        return null;
      }
      if (obj instanceof URI) {
        return (URI)obj;
      }
      throw new ModelException();
    }

    public String objectString()
      throws ModelException
    {
      Value obj = objectValue();
      if (obj == null) {
        return null;
      }
      return obj.stringValue();
    }

    @Override
    public int hashCode() {
      return size();
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o instanceof Model) {
        Model model = (Model)o;
        return ModelUtil.equals(this, model);
      }
      return false;
    }

    private ModelIterator statementIterator() {
      return match(subj, pred, obj, contexts);
    }

    private boolean accept(Statement st) {
      return matches(st, subj, pred, obj, contexts);
    }

    private boolean accept(Resource s, URI p, Value o, Resource... c) {
      if (subj != null && !subj.equals(s)) {
        return false;
      }
      if (pred != null && !pred.equals(p)) {
        return false;
      }
      if (obj != null && !obj.equals(o)) {
        return false;
      }
      if (!matches(OpenRDFUtil.notNull(c), contexts)) {
        return false;
      }
      return true;
    }
  }

  abstract class ValueSet<V extends Value> extends AbstractSet<V> {

    @Override
    public Iterator<V> iterator() {
      final Set<V> set = new LinkedHashSet<V>();
      final ModelIterator iter = statementIterator();
      return new Iterator<V>() {

        private ModelStatement current;

        private ModelStatement next;

        public boolean hasNext() {
          if (next == null) {
            next = findNext();
          }
          return next != null;
        }

        public V next() {
          if (next == null) {
            next = findNext();
            if (next == null) {
              throw new NoSuchElementException();
            }
          }
          current = next;
          next = null;
          V value = convert(current);
          set.add(value);
          return value;
        }

        public void remove() {
          if (current == null) {
            throw new IllegalStateException();
          }
          removeAll(set(node(current)), iter.getOwner());
          current = null;
        }

        private ModelStatement findNext() {
          while (iter.hasNext()) {
            ModelStatement st = iter.next();
            if (accept(st)) {
              return st;
            }
          }
          return null;
        }

        private boolean accept(ModelStatement st) {
          return !set.contains(convert(st));
        }

        private V convert(ModelStatement st) {
          return node(st).getValue();
        }
      };
    }

    @Override
    public int size() {
      Set<V> set = new LinkedHashSet<V>();
      Iterator<ModelStatement> iter = statementIterator();
      while (iter.hasNext()) {
        set.add(node(iter.next()).getValue());
      }
      return set.size();
    }

    @Override
    public boolean remove(Object o) {
      if (values.containsKey(o)) {
        return removeAll(set(values.get(o)), null);
      }
      return false;
    }

    protected abstract ModelIterator statementIterator();

    protected abstract ModelNode<V> node(ModelStatement st);

    protected abstract Set<ModelStatement> set(ModelNode<V> node);

    boolean removeAll(Set<ModelStatement> remove, Set<ModelStatement> owner) {
      if (remove.isEmpty()) {
        return false;
      }
      for (ModelStatement st : remove) {
        ModelNode<Resource> subj = st.subj;
        Set<ModelStatement> subjects = subj.subjects;
        if (subjects == owner) {
          subj.subjects = new LinkedHashSet<ModelStatement>(owner);
          subj.subjects.removeAll(remove);
        }
        else if (subjects != remove) {
          subjects.remove(st);
        }
        ModelNode<URI> pred = st.pred;
        Set<ModelStatement> predicates = pred.predicates;
        if (predicates == owner) {
          pred.predicates = new LinkedHashSet<ModelStatement>(owner);
          pred.predicates.removeAll(remove);
        }
        else if (predicates != remove) {
          predicates.remove(st);
        }
        ModelNode<Value> obj = st.obj;
        Set<ModelStatement> objects = obj.objects;
        if (objects == owner) {
          obj.objects = new LinkedHashSet<ModelStatement>(owner);
          obj.objects.removeAll(remove);
        }
        else if (objects != remove) {
          objects.remove(st);
        }
        ModelNode<Resource> ctx = st.ctx;
        Set<ModelStatement> contexts = ctx.contexts;
        if (contexts == owner) {
          ctx.contexts = new LinkedHashSet<ModelStatement>(owner);
          ctx.contexts.removeAll(remove);
        }
        else if (contexts != remove) {
          contexts.remove(st);
        }
        if (statements == owner) {
          statements = new LinkedHashSet<ModelStatement>(statements);
          statements.removeAll(remove);
        }
        else if (statements != remove && statements != owner) {
          statements.remove(st);
        }
      }
      remove.clear();
      return true;
    }
  }

  class ModelIterator implements Iterator<ModelStatement> {

    private Iterator<ModelStatement> iter;

    private Set<ModelStatement> owner;

    private ModelStatement last;

    public ModelIterator(Iterator<ModelStatement> iter, Set<ModelStatement> owner) {
      this.iter = iter;
      this.owner = owner;
    }

    public Set<ModelStatement> getOwner() {
      return owner;
    }

    public boolean hasNext() {
      return iter.hasNext();
    }

    public ModelStatement next() {
      return last = iter.next();
    }

    public void remove() {
      if (last == null) {
        throw new IllegalStateException();
      }
      removeIfNotOwner(statements);
      removeIfNotOwner(last.subj.subjects);
      removeIfNotOwner(last.pred.predicates);
      removeIfNotOwner(last.obj.objects);
      removeIfNotOwner(last.ctx.contexts);
      iter.remove(); // remove from owner
    }

    private void removeIfNotOwner(Set<ModelStatement> subjects) {
      if (subjects != owner) {
        subjects.remove(last);
      }
    }
  }

  class ModelNode<V extends Value> implements Serializable {

    private static final long serialVersionUID = -1205676084606998540L;

    Set<ModelStatement> subjects = new LinkedHashSet<ModelStatement>();

    Set<ModelStatement> predicates = new LinkedHashSet<ModelStatement>();

    Set<ModelStatement> objects = new LinkedHashSet<ModelStatement>();

    Set<ModelStatement> contexts = new LinkedHashSet<ModelStatement>();

    private V value;

    public ModelNode(V value) {
      this.value = value;
    }

    public V getValue() {
      return value;
    }

    public boolean isNull() {
      return value == null;
    }
  }

  class ModelStatement extends StatementBase {

    private static final long serialVersionUID = 2200404772364346279L;

    ModelNode<Resource> subj;

    ModelNode<URI> pred;

    ModelNode<Value> obj;

    ModelNode<Resource> ctx;

    public ModelStatement(ModelNode<Resource> subj, ModelNode<URI> pred, ModelNode<Value> obj,
        ModelNode<Resource> ctx)
    {
      assert subj != null;
      assert pred != null;
      assert obj != null;
      assert ctx != null;
      this.subj = subj;
      this.pred = pred;
      this.obj = obj;
      this.ctx = ctx;
    }

    public Resource getSubject() {
      return subj.getValue();
    }

    public URI getPredicate() {
      return pred.getValue();
    }

    public Value getObject() {
      return obj.getValue();
    }

    public Resource getContext() {
      return ctx.getValue();
    }
  }

  class PatternIterator<S extends Statement> extends FilterIterator<S> {

    private Resource subj;

    private URI pred;

    private Value obj;

    private Resource[] contexts;

    public PatternIterator(Iterator<S> iter, Resource subj, URI pred, Value obj, Resource... contexts) {
      super(iter);
      this.subj = subj;
      this.pred = pred;
      this.obj = obj;
      this.contexts = OpenRDFUtil.notNull(contexts);
    }

    @Override
    protected boolean accept(S st) {
      return matches(st, subj, pred, obj, contexts);
    }
  }

  private void writeObject(ObjectOutputStream s)
    throws IOException
  {
    // Write out any hidden serialization magic
    s.defaultWriteObject();
    // Write in size
    s.writeInt(statements.size());
    // Write in all elements
    for (ModelStatement st : statements) {
      Resource subj = st.getSubject();
      URI pred = st.getPredicate();
      Value obj = st.getObject();
      Resource ctx = st.getContext();
      s.writeObject(new StatementImpl(subj, pred, obj, ctx));
    }
  }

  private void readObject(ObjectInputStream s)
    throws IOException, ClassNotFoundException
  {
    // Read in any hidden serialization magic
    s.defaultReadObject();
    // Read in size
    int size = s.readInt();
    values = new HashMap<Value, ModelNode>(size * 2);
    statements = new LinkedHashSet<ModelStatement>(size);
    // Read in all elements
    for (int i = 0; i < size; i++) {
      Statement st = (Statement)s.readObject();
      add(st);
    }
  }

  private Iterator find(Statement st) {
    Resource subj = st.getSubject();
    URI pred = st.getPredicate();
    Value obj = st.getObject();
    Resource ctx = st.getContext();
    return match(subj, pred, obj, ctx);
  }

  private boolean addModelStatement(ModelStatement st) {
    Set<ModelStatement> subj = st.subj.subjects;
    Set<ModelStatement> pred = st.pred.predicates;
    Set<ModelStatement> obj = st.obj.objects;
    Set<ModelStatement> ctx = st.ctx.contexts;
    if (smallest(subj, pred, obj, ctx).contains(st)) {
      return false;
    }
    statements.add(st);
    subj.add(st);
    pred.add(st);
    obj.add(st);
    ctx.add(st);
    return true;
  }

  private Set<ModelStatement> smallest(Set<ModelStatement>... sets) {
    int minSize = Integer.MAX_VALUE;
    Set<ModelStatement> minSet = null;
    for (Set<ModelStatement> set : sets) {
      if (set != null && set.size() < minSize) {
        minSet = set;
      }
    }
    return minSet;
  }

  private <V extends Value> ModelNode<V> asNode(V value) {
    if (values.containsKey(value)) {
      return values.get(value);
    }
    ModelNode<V> node = new ModelNode<V>(value);
    values.put(value, node);
    return node;
  }
}
TOP

Related Classes of org.openrdf.model.impl.LinkedHashModel$ModelNode

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.