Package org.ontoware.rdfreactor.runtime

Source Code of org.ontoware.rdfreactor.runtime.ReactorMap$EntryImpl

package org.ontoware.rdfreactor.runtime;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.ontoware.aifbcommons.collection.ClosableIterator;
import org.ontoware.rdf2go.exception.ModelRuntimeException;
import org.ontoware.rdf2go.model.Model;
import org.ontoware.rdf2go.model.Statement;
import org.ontoware.rdf2go.model.node.Node;
import org.ontoware.rdf2go.model.node.Resource;
import org.ontoware.rdf2go.model.node.URI;
import org.ontoware.rdf2go.model.node.Variable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ReactorMap implements Map<URI, Object> {

  private static final Logger log = LoggerFactory.getLogger(ReactorMap.class);

  private Model model;

  private Resource id;

  public ReactorMap(Model model, Resource id) {
    this.model = model;
    this.id = id;
  }

  // ////////////////////
  // implement java.util.Map

  /**
   * warning, this is a costly operation, as it iterates over all content
   * rewriting rdf2go with Sets would maybe help
   *
   * @return number of triples matching (this, ANY, ANY)
   */
  public int size() {
    int count = 0;
    try {
      ClosableIterator<? extends Statement> it = this.model
          .findStatements(this.id, Variable.ANY, Variable.ANY);
      while (it.hasNext()) {
        it.next();
        count++;
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return count;
  }

  /**
   * @return true if model contains at least one triple (this, ANY, ANY)
   */
  public boolean isEmpty() {
    try {
      return !this.model.contains(this.id, Variable.ANY, Variable.ANY);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * @return true if model contains at least one triple (this, key, ANY)
   */
  public boolean containsKey(Object key) {
    if (key instanceof URI)
      try {
        return !this.model.contains(this.id, (URI) key, Variable.ANY);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    else {
      throw new ClassCastException("an instance of " + key.getClass()
          + " can never be contained in this map, only URIs can");
    }
  }

  /**
   * @return true if model contains at least one triple (this, ANY, value)
   * @throws ModelRuntimeException
   *             if object could not be converted to an RDF object
   */
  public boolean containsValue(Object value) {
    try {
      Node node = TypeUtils.toNode(value);
      // if no exception, node not null
      assert node != null;
      return this.model.contains(this.id, Variable.ANY, node);
    } catch (ModelRuntimeException e) {
      log.debug("an instance of " + value.getClass()
          + " can never be contained in this map");
      return false;
    }
  }

  /**
   * @return the first instance of (this, key, ANY)
   */
  public Object get(Object key) {
    if (key instanceof URI) {
      try {
        return FORD.get(this.id, (URI) key, Object.class);
      } catch (RDFDataException e) {
        // TODO: is this what users want?
        throw new RuntimeException(e);
      }
    } else
      throw new ClassCastException("an instance of " + key.getClass()
          + " can never be contained in this map, only URIs can");
  }

  /**
   * Add triple (this, key, value) to the model
   *
   * @param key
   * @param value
   * @return old value x of triple (this, key, x)
   */
  public Object put(URI key, Object value) {
    if (value == null)
      throw new NullPointerException(
          "This RDF backed Map cannot store null values");

    if (key instanceof URI) {
      Object oldValue = get(key);
      try {
        FORD.set(this.id, (URI) key, value);
      } catch (RuntimeException e) {
        throw new IllegalArgumentException(
            "Could not store value of type " + value.getClass());
      }
      return oldValue;
    } else
      throw new ClassCastException("an instance of " + key.getClass()
          + " can never be contained in this map, only URIs can");
  }

  /**
   * Remove all triples in the model matching (this, key, ANY)
   *
   * @param key,
   *            is Subject of the triple
   * @return old value x of (this, key, x)
   */
  public Object remove(Object key) {
    if (key == null)
      throw new NullPointerException("key may not be null");

    if (key instanceof URI) {
      try {
        Object oldValue = FORD.get(this.id, (URI) key, Object.class);
        FORD.removeAll(this.id, (URI) key);
        return oldValue;
      } catch (RDFDataException e) {
        // TODO: is this what users want?
        throw new RuntimeException(e);
      }
    } else
      throw new ClassCastException("an instance of " + key.getClass()
          + " can never be contained in this map, only URIs can");
  }

  /**
   * Put all URI/Object pairs in the given Map t into the model
   *
   * @param t,
   *            Map with URI/Object pairs
   */
  public void putAll(Map<? extends URI, ? extends Object> t) {
    // TODO use generics better?
    Iterator<?> it = t.entrySet().iterator();
    while (it.hasNext()) {
      Entry<?, ?> entry = (Entry) it.next();
      URI uri = (URI) entry.getKey();
      put(uri, entry.getValue());
    }
  }

  /**
   * remove all triples (this, ANY, ANY) from the model
   */
  public void clear() {
    this.model.removeStatements(this.id, Variable.ANY, Variable.ANY);
  }

  /**
   * @return all Predicates x of triples matching (this, x, ANY)
   */
  public Set<URI> keySet() {
    Set<URI> keyset = new HashSet<URI>();
    try {
      ClosableIterator<? extends Statement> it = this.model
          .findStatements(this.id, Variable.ANY, Variable.ANY);
      while (it.hasNext()) {
        keyset.add(it.next().getPredicate());
      }
      it.close();
      return keyset;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * @return all Objects x of triples matching (this, ANY, x)
   */
  public Collection<Object> values() {
    Collection<Object> values = new ArrayList<Object>();
    try {
      ClosableIterator<? extends Statement> it = this.model
          .findStatements(this.id, Variable.ANY, Variable.ANY);
      while (it.hasNext()) {
        values.add(it.next().getObject());
      }
      it.close();
      return values;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * @return a Set of Entrys, each containing a Predicate x and Object y, for
   *         every triple matching (this, x, y)
   */
  public Set<Entry<URI, Object>> entrySet() {
    Set<Entry<URI, Object>> entries = new HashSet<Entry<URI, Object>>();
    try {

      ClosableIterator<? extends Statement> it = this.model.findStatements(this.id,
          Variable.ANY, Variable.ANY);
      while (it.hasNext()) {
        Statement stmt = it.next();
        Map.Entry<URI, Object> e = new EntryImpl<URI, Object>(this,
            stmt.getPredicate(), stmt.getObject());
        entries.add(e);
      }
      it.close();
      return entries;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * <b>EntryImpl</b> is used by ReactorBaseImpl.entrySet() to keep the
   * connection between an URI x used as the subject and an Object y used as
   * the object of a statement (this, x, y) in the model.
   *
   * We habe to implement the Map.Entry<?,?> interface because we want to
   * allow setting the value of the Object y, and we need to know the
   * underlying ReactorBase instance for that.
   *
   * @author mvo
   *
   * @param <K>
   * @param <V>
   */
  class EntryImpl<K, V> implements Map.Entry<URI, Object> {

    private URI predicate;

    private Object object;

    private ReactorMap base;

    public EntryImpl(ReactorMap base, URI predicate, Object object) {
      this.predicate = predicate;
      this.object = object;
      this.base = base;
    }

    public URI getKey() {
      return this.predicate;
    }

    public Object getValue() {
      return this.object;
    }

    /**
     * Set the value x for the triple (this, predicate, x) corresponding to
     * this EntryImpl instance. We need the underlying ReactorBase instance
     * for this, because it is connected to the model.
     *
     * @param value
     *            is the Object of a triple
     * @return the old value
     */
    public Object setValue(Object value) {
      Object oldValue = this.base.get(predicate);
      FORD.set(base.id, predicate, value);
      return oldValue;
    }

  }

}
TOP

Related Classes of org.ontoware.rdfreactor.runtime.ReactorMap$EntryImpl

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.