package org.openprovenance.prov.template; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import org.openprovenance.prov.model.QualifiedName; import org.openprovenance.prov.model.TypedValue; public class Using implements Iterable<List<Integer>> { final private List<Integer> groups; final private List<Integer> lengths; public Using() { groups=new LinkedList<Integer>(); lengths=new LinkedList<Integer>(); } public void addGroup(Integer group, Integer length) { groups.add(group); lengths.add(length); } public List<Integer> zeroIndex () { List<Integer> result=new LinkedList<Integer>(); for (@SuppressWarnings("unused") Object o: lengths) { result.add(0); } return result; } public boolean checkIndex(List<Integer> index) { if (index==null) return groups.isEmpty(); if (index.size()==groups.size()) { int count=0; for (Integer in: index) { if (in >= lengths.get(count)) { return false; } count++; } return true; } return false; } public List<Integer> nextIndex(List<Integer> index) { if (!checkIndex(index)) throw new IllegalArgumentException(""+index); List<Integer> result=new LinkedList<Integer>(); int count=0; int carryOver=1; for (Integer in: index) { int next=in+carryOver; if (next >= lengths.get(count)) { next=0; carryOver=1; } else { carryOver=0; } count++; result.add(next); } if (carryOver==0) { return result; } else { return null; } } @Override public String toString () { return "<using:" + groups + "," + lengths + ">"; } Hashtable<QualifiedName, QualifiedName> get(Bindings b, Groupings gr, List<Integer> index) { Hashtable<QualifiedName,QualifiedName> result=new Hashtable<QualifiedName, QualifiedName>(); int count=0; for (int ind: index) { int group=groups.get(count); for (QualifiedName var: gr.get(group)) { List<QualifiedName> ll=b.getVariables().get(var); if (ll!=null) { QualifiedName val=ll.get(ind); result.put(var, val); } } count++; } return result; } public Hashtable<QualifiedName, List<TypedValue>> getAttr(HashSet<QualifiedName> variables, Bindings b, UsingIterator iter) { Hashtable<QualifiedName,List<TypedValue>> result=new Hashtable<QualifiedName, List<TypedValue>>(); int ind=iter.getCount(); for (QualifiedName var: variables) { List<List<TypedValue>> val=b.getAttributes().get(var); if (val!=null) { try { List<TypedValue> attVal = val.get(ind); if (attVal==null){ throw new MissingAttributeValue("Missing attribute value for variable " + var + ": index is " + ind + " and values are " + val); } result.put(var, val.get(ind)); } catch (IndexOutOfBoundsException excp) { throw new MissingAttributeValue("Missing attribute value for variable " + var + ": index is " + ind + " and values are " + val, excp); } } } return result; } public Hashtable<QualifiedName, List<TypedValue>> getAttr(Bindings b, Groupings gr, List<Integer> index) { Hashtable<QualifiedName,List<TypedValue>> result=new Hashtable<QualifiedName, List<TypedValue>>(); int count=0; for (int ind: index) { int group=groups.get(count); for (QualifiedName var: gr.get(group)) { List<List<TypedValue>> val=b.getAttributes().get(var); if (val!=null) { result.put(var, val.get(ind)); } } count++; } return result; } public class UsingIterator implements Iterator<List<Integer>> { List<Integer> currentIndex; boolean initialized; private Using u; private int count; @Override public boolean hasNext() { if (!initialized) return true; return (currentIndex!=null) && nextIndex(currentIndex)!=null; } public int getCount() { return count; } @Override public List<Integer> next() { if (!initialized) { currentIndex=u.zeroIndex(); initialized=true; count=0; return currentIndex; } if (currentIndex!=null) { currentIndex=nextIndex(currentIndex); if (currentIndex==null) { throw new NoSuchElementException(); } count++; return currentIndex; } else { throw new NoSuchElementException(); } } @Override public void remove() { throw new UnsupportedOperationException(); } public UsingIterator(Using u) { initialized=false; count = -1; this.u=u; } } @Override public Iterator<List<Integer>> iterator() { return new UsingIterator(this); } }