package org.xenei.jdbc4sparql.sparql.items;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.xenei.jdbc4sparql.iface.name.ItemName;
import org.xenei.jdbc4sparql.iface.name.NameSegments;
import org.xenei.jdbc4sparql.sparql.SparqlQueryBuilder;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
import com.hp.hpl.jena.util.iterator.Filter;
import com.hp.hpl.jena.util.iterator.Map1;
import com.hp.hpl.jena.util.iterator.UniqueFilter;
import com.hp.hpl.jena.util.iterator.WrappedIterator;
/**
* A collection of QueryItemInfo objects.
*
* locatable by
* <ul>
* <li>ItemName - uses match() to locate items.</li>
* <li>NamedObject - checks for equality of baseObject.</li>
* <li>QueryItemInfo - check for quality of objects</li>
* </ul>
*
* @param <T>
*/
public class QueryItemCollection<I extends QueryItemInfo<T, N>, T extends NamedObject<N>, N extends ItemName>
implements Collection<I> {
private List<I> lst;
public QueryItemCollection() {
lst = new ArrayList<I>();
}
public QueryItemCollection(final Collection<? extends I> initial) {
this();
addAll(initial);
}
/**
* Add a QueryItemInfo to the collection
*/
@Override
public boolean add(final I arg0) {
if (contains(arg0)) {
return false;
}
lst.add(arg0);
return true;
}
/**
* Add all items in the collection.
*/
@Override
public boolean addAll(final Collection<? extends I> arg0) {
boolean retval = false;
for (final I t : arg0) {
retval |= add(t);
}
return retval;
}
/**
* clear all the entries from the collection.
*/
@Override
public void clear() {
lst.clear();
}
// public boolean contains(ItemName name) {
// return match(name).hasNext();
// }
// public boolean contains(GUIDObject guidObj) {
// return findGUID( guidObj ) != null;
// }
// public boolean contains(NamedObject<?> arg0) {
// return match(arg0.getName()).hasNext();
// }
/**
* Executes one of the NamedObject, QueryItemInfo, and ItemName contains()
* methods or throws an IllegalArgumentException if not one of the above.
*/
@Override
public boolean contains(final Object arg0) {
if (arg0 instanceof QueryItemInfo<?, ?>) {
return contains((QueryItemInfo<?, ?>) arg0);
}
if (arg0 instanceof NamedObject<?>) {
return contains((NamedObject<?>) arg0);
}
if (arg0 instanceof ItemName) {
return contains((ItemName) arg0);
}
throw new IllegalArgumentException(
"Must be a QueryItemInfo, NamedObject, or ItemName");
}
/**
* Looks in the list for QueryItemInfo.equals( arg0 )
*
* @param arg0
* the QueryItemInfo to look for.
* @return true if it is found.
*/
public boolean contains(final QueryItemInfo<?, ?> arg0) {
return lst.contains(arg0);
}
/**
* Looks in the list for any QueryItemInfo.getBaseObject.equals();
*
* @param arg0
* the Named object to look for
* @return true if the named object is found.
*/
public boolean contains(final NamedObject<?> arg0) {
for (final QueryItemInfo<?, ?> itemInfo : lst) {
if (itemInfo.getBaseObject().getName().matches(arg0.getName())) {
return true;
}
}
return false;
}
/**
* Looks in the list of any QueryItemInfo.match( ItemName )
*
* @param arg0
* The ItemName to look for.
* @return true if the named object is found.
*/
public boolean contains(final ItemName arg0) {
return match(arg0).hasNext();
}
/**
* performs contains on all of the objects in the collection.
*/
@Override
public boolean containsAll(final Collection<?> arg0) {
for (final Object o : arg0) {
if (!contains(o)) {
return false;
}
}
return true;
}
/**
* returns true if the list is empty.
*/
@Override
public boolean isEmpty() {
return lst.isEmpty();
}
/**
* Iterator over the QueryItemInfo
*/
@Override
public ExtendedIterator<I> iterator() {
return WrappedIterator.create(lst.iterator());
}
/**
* the Set of the unique the NamedObjects
*/
public Set<T> getNamedObjectSet() {
return iterator().mapWith(new BaseObjectMap()).toSet();
}
/**
* Remove the QueryItemInfo from the list
*
* @param arg0
* The QueryItemInfo to remove
* @return true if the item was removed.
*/
public boolean remove(final QueryItemInfo<?, ?> arg0) {
return lst.remove(arg0);
}
/**
* Remove all matches for the ItemName.
*
* @param arg0
* the ItemName to remove.
* @return true if an item has been removed.
*/
public boolean remove(final ItemName arg0) {
final int startSize = lst.size();
lst = notMatch(arg0).toList();
return startSize != lst.size();
}
/**
* Remove all items that have the NamedObject as the baseObject.
*
* @param arg0
* the NamedObject to remove.
* @return true if any objects were removed.
*/
public boolean remove(final NamedObject<?> arg0) {
boolean found = false;
for (final QueryItemInfo<?, ?> itemInfo : lst) {
if (itemInfo.getBaseObject().equals(arg0)) {
found |= remove(itemInfo);
}
}
return found;
}
/**
* remove the object if it is a QueryItemInfo, NamedObject or ItemName.
*
*/
@Override
public boolean remove(final Object arg0) {
if (arg0 instanceof QueryItemInfo<?, ?>) {
return remove((QueryItemInfo<?, ?>) arg0);
}
if (arg0 instanceof NamedObject<?>) {
return remove((NamedObject<?>) arg0);
}
if (arg0 instanceof ItemName) {
return remove((ItemName) arg0);
}
throw new IllegalArgumentException(
"Must be a QueryItemInfo, NamedObject, or ItemName");
}
/**
* removes all the objects in the collection if they are a QueryItemInfo,
* NamedObject or ItemName.
*
*/
@Override
public boolean removeAll(final Collection<?> arg0) {
boolean retval = false;
for (final Object o : arg0) {
retval |= remove(o);
}
return retval;
}
/**
* retains all the objects in the collection if they are a QueryItemInfo,
* NamedObject or ItemName.
*
*/
@Override
public boolean retainAll(final Collection<?> arg0) {
if (arg0.isEmpty()) {
return false;
}
final Object o = arg0.iterator().next();
if (o instanceof QueryItemInfo<?, ?>) {
return lst.retainAll(arg0);
}
if (o instanceof NamedObject<?>) {
return retainAllNamedObject((Collection<NamedObject<?>>) arg0);
}
if (o instanceof ItemName) {
return retainAllItemName((Collection<ItemName>) arg0);
}
throw new IllegalArgumentException(
"Must be a collection of QueryItemInfo, NamedObject, or ItemName");
}
private boolean retainAllNamedObject(final Collection<NamedObject<?>> arg0) {
final List<ItemName> tmpLst = WrappedIterator.create(arg0.iterator())
.mapWith(new Map1<NamedObject<?>, ItemName>() {
@Override
public ItemName map1(final NamedObject<?> o) {
return o.getName();
}
}).toList();
return retainAllItemName(tmpLst);
}
private boolean retainAllItemName(final Collection<ItemName> arg0) {
boolean retval = false;
final List<I> newLst = new ArrayList<I>();
final List<I> dupLst = new ArrayList<I>();
I itemInfo;
dupLst.addAll(lst);
final Iterator<ItemName> outer = WrappedIterator
.create(arg0.iterator()).filterKeep(
new UniqueFilter<ItemName>());
ItemName name;
while (outer.hasNext()) {
name = outer.next();
final Iterator<I> iter = dupLst.iterator();
while (iter.hasNext()) {
itemInfo = iter.next();
if (itemInfo.getBaseObject().getName().matches(name)) {
newLst.add(itemInfo);
iter.remove();
retval = true;
}
}
}
if (retval) {
lst = newLst;
}
return retval;
}
@Override
public int size() {
return lst.size();
}
@Override
public Object[] toArray() {
return lst.toArray();
}
@Override
public <T2> T2[] toArray(final T2[] arg0) {
return lst.toArray(arg0);
}
/**
* Get the object with the specified name using the match algorithm.
*
* @param name
* The item name to find.
* @return The object for the name or null if none found
* @throws IllegalArgumentException
* if more than one object matches.
*/
public I get(final ItemName name) {
final Iterator<I> iter = match(name);
if (iter.hasNext()) {
final I retval = iter.next();
if (iter.hasNext()) {
throw new IllegalArgumentException(String.format(
SparqlQueryBuilder.FOUND_IN_MULTIPLE_, name, lst.get(0)
.getClass()));
}
return retval;
}
return null;
}
/**
* Get the object with the specified name using the match algorithm.
*
* @param namedObject
* The NamedObject to find.
* @return The object for the name or null if none found
* @throws IllegalArgumentException
* if more than one object matches.
*/
public I get(final T namedObject) {
final Iterator<I> iter = match(namedObject);
if (match(namedObject).hasNext()) {
final I retval = iter.next();
if (iter.hasNext()) {
throw new IllegalArgumentException(String.format(
SparqlQueryBuilder.FOUND_IN_MULTIPLE_, namedObject, lst
.get(0).getClass()));
}
return retval;
}
return null;
}
/**
* Return the object at position i.
*
* @param i
* the index (0 based) of the object to return.
* @return the object.
* @throws IndexOutIndexOutOfBoundsException
* if i<0 or i>=size();
*/
public I get(final int i) throws IndexOutOfBoundsException {
return lst.get(i);
}
// public I findGUID(GUIDObject name) {
// NamedObjectGUIDFilter<I> nof = new NamedObjectGUIDFilter<I>(name);
// ExtendedIterator<I> iter = iterator().filterKeep(nof);
// if (iter.hasNext()) {
// return iter.next();
// }
// return null;
//
// }
//
public I findGUIDVar(final String guid) {
final ExtendedIterator<I> iter = iterator();
I backupResult = null;
while (iter.hasNext()) {
final I item = iter.next();
if (item.getName().getGUID().equals(guid)) {
return item;
}
if ((backupResult == null) && item.getGUID().equals(guid)) {
backupResult = item;
}
}
return backupResult;
}
public int count(final ItemName name) {
return match(name).toList().size();
}
public int count(final T namedObject) {
return match(namedObject).toList().size();
}
public ExtendedIterator<I> match(final ItemName name) {
final ItemNameFilter<I> nof = new ItemNameFilter<I>(name);
return iterator().filterKeep(nof);
}
public ExtendedIterator<I> match(final T name) {
final NamedObjectFilter<I> nof = new NamedObjectFilter<I>(name);
return iterator().filterKeep(nof);
}
public ExtendedIterator<I> findBaseObject(final T baseObject) {
return iterator().filterKeep(new BaseObjectFilter<I>(baseObject));
}
public ExtendedIterator<I> notMatch(final ItemName name) {
final ItemNameFilter<I> nof = new ItemNameFilter<I>(name);
return iterator().filterDrop(nof);
}
public ExtendedIterator<I> notMatch(final T namedObject) {
final NamedObjectFilter<I> nof = new NamedObjectFilter<I>(namedObject);
return iterator().filterDrop(nof);
}
public int indexOf(final QueryItemInfo<?, ?> item) {
return lst.indexOf(item);
}
public int indexOf(final T namedObject) {
final NamedObjectFilter<I> nof = new NamedObjectFilter<I>(namedObject);
final Iterator<I> iter = iterator();
int i = 0;
while (iter.hasNext()) {
if (nof.accept(iter.next())) {
return i;
}
i++;
}
return -1;
}
public int indexOf(final ItemName name) {
final ItemNameFilter<I> nof = new ItemNameFilter<I>(name);
final Iterator<I> iter = iterator();
int i = 0;
while (iter.hasNext()) {
if (nof.accept(iter.next())) {
return i;
}
i++;
}
return -1;
}
@Override
public String toString() {
return lst.toString();
}
public static class ItemNameFilter<I extends QueryItemInfo<?, ?>> extends
Filter<I> {
protected Collection<ItemName> others;
public ItemNameFilter(final ItemName other) {
this.others = new ArrayList<ItemName>();
this.others.add(other);
}
public ItemNameFilter(final Collection<?> others) {
this.others = new ArrayList<ItemName>();
for (final Object t : others) {
if (t instanceof ItemName) {
this.others.add((ItemName) t);
}
else if (t instanceof NamedObject) {
this.others.add(((NamedObject<?>) t).getName());
}
else {
throw new IllegalArgumentException(String.format(
"%s is not an instance of ItemName or NamedObject",
t.getClass()));
}
}
}
@Override
public boolean accept(final I item) {
final ItemName name = item.getName().clone(NameSegments.ALL);
for (final ItemName other : others) {
if (other.matches(name)) {
return true;
}
}
return false;
}
}
public class BaseObjectMap implements Map1<I, T> {
@Override
public T map1(final I o) {
return o.getBaseObject();
}
}
public class BaseObjectFilter<I extends QueryItemInfo<?, ?>> extends
Filter<I> {
protected Collection<T> others;
public BaseObjectFilter(final T other) {
this.others = new ArrayList<T>();
this.others.add(other);
}
public BaseObjectFilter(final Collection<?> others) {
this.others = new ArrayList<T>();
for (final Object t : others) {
if (t instanceof NamedObject<?>) {
this.others.add((T) t);
}
else {
throw new IllegalArgumentException(String.format(
"%s is not an instance of ItemName or NamedObject",
t.getClass()));
}
}
}
@Override
public boolean accept(final I item) {
for (final T other : others) {
if (other.getName().getGUID()
.equals(item.getBaseObject().getName().getGUID())) {
return true;
}
}
return false;
}
}
}