/******************************************************************************* * Copyright (c) 2004, 2007-2008 IBM Corporation and Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * File: $Source: * Created by: Ben Szekely (<a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com</a>) * Created on: 6/1/05 * Revision: $Id: interface.javajet 172 2007-07-31 14:22:23Z mroy $ * * Contributors: * IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.rdf.jastor.collections.util; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import org.openanzo.rdf.Constants; import org.openanzo.rdf.IDataset; import org.openanzo.rdf.Literal; import org.openanzo.rdf.PlainLiteral; import org.openanzo.rdf.Resource; import org.openanzo.rdf.TypedLiteral; import org.openanzo.rdf.URI; import org.openanzo.rdf.jastor.JastorException; import org.openanzo.rdf.jastor.Thing; import org.openanzo.rdf.jastor.ThingFactory; import org.openanzo.rdf.jastor.ThingImpl; import org.openanzo.rdf.jastor.collections.Collection; import org.openanzo.rdf.jastor.collections.CollectionsFactory; import org.openanzo.rdf.jastor.collections.Item; import org.openanzo.rdf.jastor.collections.LiteralItem; import org.openanzo.rdf.jastor.collections.OrderedCollection; import org.openanzo.rdf.jastor.collections.OrderedItem; import org.openanzo.rdf.jastor.collections.ResourceItem; /** * * This utility class provides a standard java.util.Collection view of http://openanzo.org/ontologies/Collections. * * @author Ben Szekely ( <a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com </a>) * */ @SuppressWarnings("unchecked") public class CollectionWrapper implements java.util.Collection { final private Collection c; final private boolean isOrdered; OrderedCollection oc = null; private OrderedItem lastItem; private IDataset dataset; private URI namedGraphUri; private Class<? extends ThingFactory>[] factoryClasses; private List<Method> methods; private ItemFactory itemFactory; final private boolean nullCollection; /** * Create a wrapper around the collection * * @param collection * collection to wrap * @param factoryClasses * factory for classes * @param itemFactory * item factory */ public CollectionWrapper(Collection collection, Class<? extends ThingFactory>[] factoryClasses, ItemFactory itemFactory) { if (collection == null) { this.nullCollection = true; this.isOrdered = false; this.c = null; } else { this.nullCollection = false; this.dataset = collection.dataset(); this.namedGraphUri = collection.graph().getNamedGraphUri(); this.c = collection; this.isOrdered = collection instanceof OrderedCollection; if (isOrdered) { this.oc = (OrderedCollection) collection; try { if (oc.getCollectionSize() == null) oc.setCollectionSize(Integer.valueOf(0)); this.lastItem = oc.getFirstItem(); while (this.lastItem != null && this.lastItem.getNextItem() != null) this.lastItem = this.lastItem.getNextItem(); } catch (JastorException e) { e.printStackTrace(); } } } this.itemFactory = itemFactory; this.factoryClasses = factoryClasses; if (this.factoryClasses != null) { methods = new ArrayList<Method>(); try { for (Class<? extends ThingFactory> clazz : factoryClasses) { methods.add(clazz.getMethod("getThing", new Class[] { Resource.class, URI.class, IDataset.class })); } } catch (NoSuchMethodException e) { e.printStackTrace(); } } } /** * Create a wrapper around the collection * * @param collection * collection to wrap * @param factoryClasses * factory for classes */ public CollectionWrapper(Collection collection, Class<? extends ThingFactory>[] factoryClasses) { this(collection, factoryClasses, null); } /** * Create a wrapper around the collection * * @param collection * collection to wrap * @param factoryClass * factory for classes */ public CollectionWrapper(Collection collection, Class<? extends ThingFactory> factoryClass) { this(collection, new Class[] { factoryClass }); } /** * Create a wrapper around the collection * * @param collection * collection to wrap */ public CollectionWrapper(Collection collection) { this(collection, (Class[]) null); } public boolean add(Object o) { if (nullCollection) throw new UnsupportedOperationException(); try { Item item = null; if (itemFactory != null) { item = itemFactory.createItem(Constants.valueFactory.createBNode(), namedGraphUri, dataset); } if (o instanceof Thing) { if (item == null) { item = CollectionsFactory.createResourceItem(Constants.valueFactory.createBNode(), namedGraphUri, dataset); } ((ResourceItem) item).setItemObject((Thing) o); } else if (o instanceof Resource) { if (item == null) { item = CollectionsFactory.createResourceItem(Constants.valueFactory.createBNode(), namedGraphUri, dataset); } ((ResourceItem) item).setItemObject(ThingFactory.createThing((Resource) o, namedGraphUri, dataset)); } else { if (item == null) item = CollectionsFactory.createLiteralItem(Constants.valueFactory.createBNode(), namedGraphUri, dataset); Literal lit = null; if (o instanceof Literal) lit = (Literal) o; else lit = Constants.valueFactory.createTypedLiteral(o); ((LiteralItem) item).setItemData(lit); } if (isOrdered) { OrderedItem oitem = CollectionsFactory.createOrderedItem(item.resource(), namedGraphUri, dataset); if (lastItem == null) { lastItem = oitem; } else { lastItem.setNextItem(oitem); oitem.setPreviousItem(lastItem); lastItem = oitem; } OrderedItem firstItem = oc.getFirstItem(); if (firstItem == null) { oc.setFirstItem(oitem); } int size = oc.getCollectionSize().intValue(); oc.setCollectionSize(Integer.valueOf(size + 1)); } c.addItem(item); return true; } catch (JastorException e) { e.printStackTrace(); return false; } } public boolean addAll(java.util.Collection collection) { if (nullCollection) throw new UnsupportedOperationException(); Iterator it = collection.iterator(); boolean success = true; while (it.hasNext()) { if (!add(it.next())) { success = false; } } return success; } public void clear() { if (nullCollection) throw new UnsupportedOperationException(); Iterator it = iterator(); while (it.hasNext()) { remove(it.next()); } } public boolean contains(Object o) { if (nullCollection) return false; Iterator it = iterator(); while (it.hasNext()) { if (o.equals(it.next())) { return true; } } return false; } public boolean containsAll(java.util.Collection c) { if (nullCollection) return false; Iterator it = c.iterator(); while (it.hasNext()) { if (!contains(it.next())) { return false; } } return true; } public boolean isEmpty() { if (nullCollection) return true; if (isOrdered) return lastItem == null; else { try { java.util.Collection<Item> items = c.getItem(); boolean empty = items.isEmpty(); return empty; } catch (JastorException e) { e.printStackTrace(); return false; } } } private Thing getThing(Thing res) { if (factoryClasses == null) return res; else { try { for (Method method : methods) { // we can speed things up here caching the method perhaps Thing thing = (Thing) method.invoke(null, new Object[] { res.resource(), res.graph().getNamedGraphUri(), dataset }); if (!(thing.getClass().equals(ThingImpl.class))) return thing; } } catch (InvocationTargetException ite) { ite.printStackTrace(); return res; } catch (IllegalAccessException ite) { ite.printStackTrace(); return res; } return res; } } public Iterator iterator() { if (nullCollection) return Collections.unmodifiableList(new ArrayList()).iterator(); if (isOrdered) { return new Iterator() { private OrderedItem currentItem = null; public void remove() { CollectionWrapper.this.remove(currentItem); } public boolean hasNext() { try { if (currentItem == null) return oc.getFirstItem() != null; else return currentItem.getNextItem() != null; } catch (JastorException e) { e.printStackTrace(); return false; } } public Object next() { if (!hasNext()) throw new NoSuchElementException(); try { if (currentItem == null) currentItem = oc.getFirstItem(); else currentItem = currentItem.getNextItem(); Object toReturn = null; if (currentItem.isRDFType(ResourceItem.TYPE)) { ResourceItem resItem = CollectionsFactory.getResourceItem(currentItem.resource(), namedGraphUri, dataset); toReturn = getThing(resItem.getItemObject()); } else if (currentItem.isRDFType(LiteralItem.TYPE)) { LiteralItem literalItem = CollectionsFactory.getLiteralItem(currentItem.resource(), namedGraphUri, dataset); Literal lit = literalItem.getItemData(); if (lit instanceof TypedLiteral) { toReturn = ((TypedLiteral) lit).getNativeValue(); } else { toReturn = lit.getLabel(); } } else { throw new RuntimeException("OrderedCollectionIterator supports only subclasses of ResourceItem and LiteralItem."); } return toReturn; } catch (JastorException e) { e.printStackTrace(); throw new NoSuchElementException(); } } }; } else { try { final Iterator<Item> it = c.getItem().iterator(); return new Iterator() { private Item currentItem = null; public void remove() { CollectionWrapper.this.remove(currentItem); } public boolean hasNext() { return it.hasNext(); } public Object next() { if (!hasNext()) throw new NoSuchElementException(); try { currentItem = it.next(); Object toReturn = null; if (currentItem.isRDFType(ResourceItem.TYPE)) { ResourceItem resItem = CollectionsFactory.getResourceItem(currentItem.resource(), namedGraphUri, dataset); toReturn = getThing(resItem.getItemObject()); } else if (currentItem.isRDFType(LiteralItem.TYPE)) { LiteralItem literalItem = CollectionsFactory.getLiteralItem(currentItem.resource(), namedGraphUri, dataset); Literal lit = literalItem.getItemData(); if (lit instanceof TypedLiteral) { toReturn = ((TypedLiteral) lit).getNativeValue(); } else { toReturn = lit.getLabel(); } } else { throw new RuntimeException("OrderedCollectionIterator supports only subclasses of ResourceItem and LiteralItem."); } return toReturn; } catch (JastorException e) { e.printStackTrace(); throw new NoSuchElementException(); } } }; } catch (JastorException e) { e.printStackTrace(); return null; } } } public boolean remove(Object o) { if (nullCollection) throw new UnsupportedOperationException(); try { // find the item that contains the object Iterator<Item> it = c.getItem().iterator(); Item item = null; while (it.hasNext()) { Item next = it.next(); if (next.isRDFType(ResourceItem.TYPE)) { if (o instanceof Thing) { ResourceItem resItem = CollectionsFactory.getResourceItem(next.resource(), namedGraphUri, dataset); if (resItem.getItemObject().equals(o)) { item = resItem; resItem.removeStatements(); break; } } else if (o instanceof Resource) { ResourceItem resItem = CollectionsFactory.getResourceItem(next.resource(), namedGraphUri, dataset); if (resItem.getItemObject().uri().equals(((URI) o).toString())) { item = resItem; resItem.removeStatements(); break; } } } else { if (o instanceof Thing || o instanceof Resource) continue; LiteralItem litItem = CollectionsFactory.getLiteralItem(next.resource(), namedGraphUri, dataset); Literal lit = litItem.getItemData(); if (lit instanceof PlainLiteral) { if (litItem.getItemData().getLabel().equals(o.toString())) { item = litItem; litItem.removeStatements(); break; } } else { TypedLiteral tl = (TypedLiteral) lit; if (tl.getNativeValue().equals(o)) { item = litItem; litItem.removeStatements(); break; } } } } // the user may be attempting to remove an item that is not in the collection if (item != null) { c.removeItem(item); if (isOrdered) { OrderedItem oItem = CollectionsFactory.getOrderedItem(item.resource(), namedGraphUri, dataset); if (lastItem.equals(item)) { lastItem = oItem.getPreviousItem(); } if (oc.getFirstItem().equals(oItem)) { oc.setFirstItem(oItem.getNextItem()); } if (oItem.getPreviousItem() != null) oItem.getPreviousItem().setNextItem(oItem.getNextItem()); if (oItem.getNextItem() != null) oItem.getNextItem().setPreviousItem(oItem.getPreviousItem()); oc.setCollectionSize(Integer.valueOf(oc.getCollectionSize().intValue() - 1)); oItem.removeStatements(); } return true; } } catch (JastorException e) { e.printStackTrace(); return false; } return false; } public boolean removeAll(java.util.Collection collection) { if (nullCollection) throw new UnsupportedOperationException(); Iterator it = collection.iterator(); boolean success = true; while (it.hasNext()) { if (!remove(it.next())) success = false; } return success; } public boolean retainAll(java.util.Collection collection) { if (nullCollection) throw new UnsupportedOperationException(); Iterator it = iterator(); while (it.hasNext()) { if (!collection.contains(it.next())) it.remove(); } return true; } public int size() { if (nullCollection) return 0; try { if (isOrdered) { return oc.getCollectionSize().intValue(); } else { return c.getItem().size(); } } catch (JastorException e) { e.printStackTrace(); return -1; } } public Object[] toArray() { if (nullCollection) return new Object[] {}; List list = new ArrayList(); Iterator it = iterator(); while (it.hasNext()) { list.add(it.next()); } return list.toArray(); } public Object[] toArray(Object[] a) { if (nullCollection) return new Object[] {}; Iterator it = iterator(); int i = 0; while (it.hasNext()) { a[i++] = it.next(); } return a; } }