Package org.apache.clerezza.rdf.core.impl

Source Code of org.apache.clerezza.rdf.core.impl.AbstractTripleCollection

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.clerezza.rdf.core.impl;

import java.lang.ref.WeakReference;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;

import java.util.Set;
import org.apache.clerezza.rdf.core.NonLiteral;
import org.apache.clerezza.rdf.core.Resource;
import org.apache.clerezza.rdf.core.Triple;
import org.apache.clerezza.rdf.core.TripleCollection;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.event.AddEvent;
import org.apache.clerezza.rdf.core.event.FilterTriple;
import org.apache.clerezza.rdf.core.event.GraphEvent;
import org.apache.clerezza.rdf.core.event.GraphListener;
import org.apache.clerezza.rdf.core.event.RemoveEvent;

/**
* An abstract implementation of <code>TripleCollection</code> implementing
* <code>iterator</code> and <code>contains</code> calling <code>filter</code>.
*
* @author reto
*/
public abstract class AbstractTripleCollection extends AbstractCollection<Triple>
    implements TripleCollection {

  //all listeners
  private final Set<ListenerConfiguration> listenerConfigs = Collections.synchronizedSet(
      new HashSet<ListenerConfiguration>());
  private DelayedNotificator delayedNotificator = new DelayedNotificator();

  @Override
  public Iterator<Triple> iterator() {
    return filter(null, null, null);
  }

  @Override
  public boolean contains(Object o) {
    if (!(o instanceof Triple)) {
      return false;
    }
    Triple t = (Triple) o;
    return filter(t.getSubject(), t.getPredicate(), t.getObject()).hasNext();
  }

  @Override
  public Iterator<Triple> filter(NonLiteral subject, UriRef predicate,
      Resource object) {
    final Iterator<Triple> baseIter = performFilter(subject, predicate, object);
    return new Iterator<Triple>() {

      Triple currentTriple = null;

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

      @Override
      public Triple next() {
        currentTriple = baseIter.next();
        return currentTriple;
      }

      @Override
      public void remove() {
        baseIter.remove();
        dispatchEvent(new RemoveEvent(AbstractTripleCollection.this, currentTriple));
      }
    };
  }

  /**
   * A subclass of <code>AbstractTripleCollection</code> should override
   * this method instead of <code>filter</code> for graph event support to be
   * added. The Iterator returned by <code>filter</code> will dispatch a
   * GraphEvent after invoking the remove method of the iterator returned by
   * this method.
   *
   * @param subject
   * @param predicate
   * @param object
   * @return
   */
  protected abstract Iterator<Triple> performFilter(NonLiteral subject, UriRef predicate,
      Resource object);

  @Override
  public boolean add(Triple triple) {
    boolean success = performAdd(triple);
    if (success) {
      dispatchEvent(new AddEvent(this, triple));
    }
    return success;
  }

  /**
   * A subclass of <code>AbstractTripleCollection</code> should override
   * this method instead of <code>add</code> for graph event support to be
   * added.
   *
   * @param e The triple to be added to the triple collection
   * @return
   */
  protected boolean performAdd(Triple e) {
    return super.add(e);
  }

  @Override
  public boolean remove(Object o) {
    Triple triple = (Triple) o;
    boolean success = performRemove(triple);
    if (success) {
      dispatchEvent(new RemoveEvent(this, triple));
    }
    return success;
  }

  @Override
  public boolean removeAll(Collection<?> c) {
    boolean modified = false;
    for (Iterator<? extends Object> it = c.iterator(); it.hasNext();) {
      Object object = it.next();
      if (remove(object)) {
        modified = true;
      }
    }
    return modified;
  }

  /**
   * A subclass of <code>AbstractTripleCollection</code> should override
   * this method instead of <code>remove</code> for graph event support to be
   * added.
   *
   * @param o The triple to be removed from the triple collection
   * @return
   */
  protected boolean performRemove(Triple triple) {
    Iterator<Triple> e = performFilter(null, null, null);
    while (e.hasNext()) {
      if (triple.equals(e.next())) {
        e.remove();
        return true;
      }
    }
    return false;
  }

  /**
   * Dispatches a <code>GraphEvent</code> to all registered listeners for which
   * the specified <code>Triple</code> matches the <code>FilterTriple</code>s
   * of the listeners.
   *
   * @param triple The Triple that was modified
   * @param type The type of modification
   */
  protected void dispatchEvent(GraphEvent event) {
    synchronized(listenerConfigs) {
      Iterator<ListenerConfiguration> iter = listenerConfigs.iterator();
      while (iter.hasNext()) {
        ListenerConfiguration config = iter.next();
        GraphListener registeredListener = config.getListener();
        if (registeredListener == null) {
          iter.remove();
          continue;
        }
        if (config.getFilter().match(event.getTriple())) {
          delayedNotificator.sendEventToListener(registeredListener, event);
        }
      }
    }
  }

  @Override
  public void addGraphListener(GraphListener listener, FilterTriple filter) {
    addGraphListener(listener, filter, 0);
  }

  @Override
  public void addGraphListener(GraphListener listener, FilterTriple filter,
      long delay) {
    listenerConfigs.add(new ListenerConfiguration(listener, filter));
    if (delay > 0) {
      delayedNotificator.addDelayedListener(listener, delay);
    }
  }

  @Override
  public void removeGraphListener(GraphListener listener) {
    synchronized(listenerConfigs) {
      Iterator<ListenerConfiguration> iter = listenerConfigs.iterator();
      while (iter.hasNext()) {
        ListenerConfiguration listenerConfig = iter.next();
        GraphListener registeredListener = listenerConfig.getListener();
        if ((registeredListener == null) || (registeredListener.equals(listener))) {
          iter.remove();
        }
      }
    }
    delayedNotificator.removeDelayedListener(listener);
  }

  private static class ListenerConfiguration {

    private WeakReference<GraphListener> listenerRef;
    private FilterTriple filter;

    private ListenerConfiguration(GraphListener listener, FilterTriple filter) {
      this.listenerRef = new WeakReference<GraphListener>(listener);
      this.filter = filter;
    }

    /**
     * @return the listener
     */
    GraphListener getListener() {
      GraphListener listener = listenerRef.get();
      return listener;
    }

    /**
     * @return the filter
     */
    FilterTriple getFilter() {
      return filter;
    }
  }
}
TOP

Related Classes of org.apache.clerezza.rdf.core.impl.AbstractTripleCollection

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.