package org.openprovenance.prov.template; import java.util.HashSet; import java.util.Hashtable; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; import java.util.Set; import org.openprovenance.prov.model.Attribute; import org.openprovenance.prov.model.Bundle; import org.openprovenance.prov.model.Document; import org.openprovenance.prov.model.Entity; import org.openprovenance.prov.model.Name; import org.openprovenance.prov.model.Namespace; import org.openprovenance.prov.model.Other; import org.openprovenance.prov.model.ProvFactory; import org.openprovenance.prov.model.ProvUtilities; import org.openprovenance.prov.model.QualifiedName; import org.openprovenance.prov.model.Statement; import org.openprovenance.prov.model.StatementOrBundle; import org.openprovenance.prov.model.TypedValue; import org.openprovenance.prov.template.BindingsJson.BindingsBean; import static org.openprovenance.prov.template.ExpandUtil.TMPL_NS; import static org.openprovenance.prov.template.ExpandUtil.TMPL_PREFIX; public class Bindings { public static final String VALUE = "value_"; public static final String VALUE2 = "2dvalue_"; public static final String APP_VALUE = TMPL_NS+VALUE; public static final String VALUE_v2 = "binding_"; public static final String APP_VALUE_v2 = TMPL_NS+VALUE_v2; public static final String APP_VALUE2 = TMPL_NS+VALUE2; final private Hashtable<QualifiedName, List<QualifiedName>> variables; final private Hashtable<QualifiedName, List<List<TypedValue>>> attributes; final private ProvFactory pf; final private Name name; static ProvUtilities u= new ProvUtilities(); public Bindings(ProvFactory pf) { this(new Hashtable<QualifiedName, List<QualifiedName>>(), new Hashtable<QualifiedName, List<List<TypedValue>>>(), pf); } public Bindings(Hashtable<QualifiedName, List<QualifiedName>> variables, Hashtable<QualifiedName, List<List<TypedValue>>> attributes, ProvFactory pf) { this.variables=variables; this.attributes=attributes; this.pf=pf; this.name=pf.getName(); } @Override public boolean equals (Object o) { if (!(o instanceof Bindings)) return false; Bindings b=(Bindings)o; return b.variables.equals(this.variables) && b.attributes.equals(this.attributes); } public Hashtable<QualifiedName, List<QualifiedName>> getVariables() { return variables; } public Hashtable<QualifiedName, List<List<TypedValue>>> getAttributes() { return attributes; } public void addVariable(QualifiedName name, QualifiedName val) { List<QualifiedName> v=variables.get(name); if (v==null) { variables.put(name, new LinkedList<QualifiedName>()); } variables.get(name).add(val); } public void addVariable(String name, QualifiedName val) { addVariable(b_var(name),val); } public void addAttribute(QualifiedName name, List<TypedValue> values) { List<List<TypedValue>> v=attributes.get(name); if (v==null) { attributes.put(name, new LinkedList<List<TypedValue>>()); } attributes.get(name).add(values); } public void addAttribute(String name, QualifiedName value) { addAttribute(b_var(name),a_val(value)); } public void addAttribute(String name, String value) { addAttribute(b_var(name),a_val(value)); } /* binding variable */ public QualifiedName b_var(String name) { return pf.newQualifiedName(ExpandUtil.VAR_NS, name, ExpandUtil.VAR_PREFIX); } /** Attribute value */ public List<TypedValue> a_val(String s) { List<TypedValue> ll=new LinkedList<TypedValue>(); ll.add(pf.newAttribute(pf.newQualifiedName(TMPL_NS, "ignore", "app"), s, name.XSD_STRING)); return ll; } public List<TypedValue> a_val(QualifiedName s) { List<TypedValue> ll=new LinkedList<TypedValue>(); ll.add(pf.newAttribute(pf.newQualifiedName(TMPL_NS, "ignore", "app"), s, name.PROV_QUALIFIED_NAME)); return ll; } @Override public String toString () { return "[" + getVariables() + " -- " + getAttributes() + "]"; } public Document toDocument () { List<Statement> ll=new LinkedList<Statement>(); add1DValues(ll,variables); add2Dvalues(ll,attributes); Document dummy=pf.newDocument(null,ll,new LinkedList<Bundle>()); Document result=pf.newDocument(pf.newNamespace(Namespace.gatherNamespaces(dummy)),ll,new LinkedList<Bundle>()); return result; } public Document toDocument_v2 () { List<Statement> ll=new LinkedList<Statement>(); add1DValues_v2(ll,variables); add2Dvalues_v2(ll,attributes); Document dummy=pf.newDocument(null,ll,new LinkedList<Bundle>()); Document result=pf.newDocument(pf.newNamespace(Namespace.gatherNamespaces(dummy)),ll,new LinkedList<Bundle>()); return result; } public void add2DvaluesOLD(List<StatementOrBundle> ll, Hashtable<QualifiedName, List<List<TypedValue>>> attributes) { for (Entry<QualifiedName, List<List<TypedValue>>> entry: attributes.entrySet()) { Entity e=pf.newEntity(entry.getKey()); int count1=0; List<Other> attrs=new LinkedList<Other>(); for (List<TypedValue> vals: entry.getValue()) { int count2=0; for (TypedValue val: vals) { attrs.add(pf.newOther(TMPL_NS, VALUE2+count1+"_"+count2, TMPL_PREFIX, val.getValue(), val.getType())); count2++; } count1++; } e.getOther().addAll(attrs); ll.add(e); } } public void add2Dvalues(List<Statement> ll, Hashtable<QualifiedName, List<List<TypedValue>>> attributes) { for (Entry<QualifiedName, List<List<TypedValue>>> entry: attributes.entrySet()) { int count1=0; List<Attribute> attrs=new LinkedList<Attribute>(); for (List<TypedValue> vals: entry.getValue()) { int count2=0; for (TypedValue val: vals) { attrs.add(pf.newAttribute(TMPL_NS, VALUE2+count1+"_"+count2, TMPL_PREFIX, val.getValue(), val.getType())); count2++; } count1++; } Entity e=pf.newEntity(entry.getKey(),attrs); ll.add(e); } } public void add2Dvalues_v2(List<Statement> ll, Hashtable<QualifiedName, List<List<TypedValue>>> attributes) { for (Entry<QualifiedName, List<List<TypedValue>>> entry: attributes.entrySet()) { int count1=0; List<Attribute> attrs=new LinkedList<Attribute>(); for (List<TypedValue> vals: entry.getValue()) { //int count2=0; for (TypedValue val: vals) { attrs.add(pf.newAttribute(TMPL_NS, VALUE_v2+count1, TMPL_PREFIX, val.getValue(), val.getType())); //count2++; } count1++; } Entity e=pf.newEntity(entry.getKey(),attrs); ll.add(e); } } public void add1DValuesOLD(List<StatementOrBundle> ll, Hashtable<QualifiedName, List<QualifiedName>> variables) { for (Entry<QualifiedName, List<QualifiedName>> entry: variables.entrySet()) { Entity e=pf.newEntity(entry.getKey()); int count=0; List<Attribute> attrs=new LinkedList<Attribute>(); for (QualifiedName qn: entry.getValue()) { attrs.add(pf.newAttribute(TMPL_NS, VALUE+count, TMPL_PREFIX, qn, pf.getName().PROV_QUALIFIED_NAME)); count++; } pf.setAttributes(e, attrs); ll.add(e); } } public void add1DValues(List<Statement> ll, Hashtable<QualifiedName, List<QualifiedName>> variables) { for (Entry<QualifiedName, List<QualifiedName>> entry: variables.entrySet()) { int count=0; List<Attribute> attrs=new LinkedList<Attribute>(); for (QualifiedName qn: entry.getValue()) { attrs.add(pf.newAttribute(TMPL_NS, VALUE+count, TMPL_PREFIX, qn, pf.getName().PROV_QUALIFIED_NAME)); count++; } Entity e=pf.newEntity(entry.getKey(),attrs); ll.add(e); } } public void add1DValues_v2(List<Statement> ll, Hashtable<QualifiedName, List<QualifiedName>> variables) { for (Entry<QualifiedName, List<QualifiedName>> entry: variables.entrySet()) { int count=0; List<Attribute> attrs=new LinkedList<Attribute>(); for (QualifiedName qn: entry.getValue()) { attrs.add(pf.newAttribute(TMPL_NS, VALUE_v2+count, TMPL_PREFIX, qn, pf.getName().PROV_QUALIFIED_NAME)); count++; } Entity e=pf.newEntity(entry.getKey(),attrs); ll.add(e); } } public static Bindings fromDocument(Document doc,ProvFactory pf) { Bindings result=new Bindings(pf); List<Entity> entities=u.getEntity(doc); for (Entity entity: entities) { Hashtable<Integer,QualifiedName> map=new Hashtable<Integer, QualifiedName>(); Hashtable<Integer, Hashtable<Integer,TypedValue>> map2=new Hashtable<Integer, Hashtable<Integer,TypedValue>>(); for (Other attr: entity.getOther()) { String uri = attr.getElementName().getUri(); if (uri.startsWith(APP_VALUE)) { Integer i=Integer.valueOf(uri.substring(APP_VALUE.length())); if (attr.getValue() instanceof QualifiedName) { map.put(i, (QualifiedName) attr.getValue()); } } else { if (uri.startsWith(APP_VALUE2)) { String index=uri.substring(APP_VALUE2.length()); String [] nums=index.split("_"); Integer i=Integer.valueOf(nums[0]); Integer j=Integer.valueOf(nums[1]); Hashtable<Integer, TypedValue> row=map2.get(i); if (row==null) map2.put(i, new Hashtable<Integer, TypedValue>()); map2.get(i).put(j,attr); } } } ArrayList<QualifiedName> ll=new ArrayList<QualifiedName>(); int size=map.entrySet().size(); if (size>0) { for (Entry<Integer, QualifiedName> entry: map.entrySet()) { set(entry.getKey(),ll,entry.getValue()); } result.getVariables().put(entity.getId(),ll); } int size2=map2.entrySet().size(); if (size2>0) { List<List<TypedValue>> allvalues= new LinkedList<List<TypedValue>>(); for (Entry<Integer, Hashtable<Integer, TypedValue>> entry1: map2.entrySet()) { List<TypedValue> values= new LinkedList<TypedValue>(); for (Entry<Integer, TypedValue> entry2: entry1.getValue().entrySet()) { set(entry2.getKey(),values,entry2.getValue()); } set(entry1.getKey(),allvalues,values); } result.getAttributes().put(entity.getId(),allvalues); } } return result; } public static Bindings fromDocument_v2(Document doc,ProvFactory pf) { Bindings result=new Bindings(pf); List<Entity> entities=u.getEntity(doc); for (Entity entity: entities) { Hashtable<Integer,QualifiedName> map=new Hashtable<Integer, QualifiedName>(); //Hashtable<Integer, Hashtable<Integer,TypedValue>> map2=new Hashtable<Integer, Hashtable<Integer,TypedValue>>(); Hashtable<Integer, Set<TypedValue>> map_v2=new Hashtable<Integer, Set<TypedValue>>(); for (Other attr: entity.getOther()) { String uri = attr.getElementName().getUri(); if (uri.startsWith(APP_VALUE_v2)) { String index=uri.substring(APP_VALUE_v2.length()); Integer i=Integer.valueOf(index); Set<TypedValue> row=map_v2.get(i); if (row==null) map_v2.put(i, new HashSet<TypedValue>()); map_v2.get(i).add(attr); } else { if (uri.startsWith(APP_VALUE)) { Integer i=Integer.valueOf(uri.substring(APP_VALUE.length())); Set<TypedValue> row=map_v2.get(i); if (row==null) map_v2.put(i, new HashSet<TypedValue>()); map_v2.get(i).add(attr); } } } // reconstructing the map data structure for variables uniquely mapped to qualified names. boolean single_map=true; for (int i: map_v2.keySet()) { single_map=single_map && (map_v2.get(i).size()==1); if (single_map) { for (TypedValue tv: map_v2.get(i)) { // only one element to iterate over single_map=(tv.getValue() instanceof QualifiedName) ; } } } if (single_map) { for (int i: map_v2.keySet()) { for (TypedValue tv: map_v2.get(i)) { // only one element to iterate over map.put(i, (QualifiedName) tv.getValue()); } } } ArrayList<QualifiedName> ll=new ArrayList<QualifiedName>(); int size=map.entrySet().size(); if (size>0) { for (Entry<Integer, QualifiedName> entry: map.entrySet()) { set(entry.getKey(),ll,entry.getValue()); } result.getVariables().put(entity.getId(),ll); } int size2=map_v2.entrySet().size(); if (size2>0) { List<List<TypedValue>> allvalues= new LinkedList<List<TypedValue>>(); for (Entry<Integer, Set<TypedValue>> entry1: map_v2.entrySet()) { List<TypedValue> values= new LinkedList<TypedValue>(); //convert to 2dvalue int count=0; for (TypedValue tv: entry1.getValue()) { if (tv instanceof Other) { Other o=(Other)tv; String uri = o.getElementName().getUri(); if (uri.startsWith(APP_VALUE_v2)) { Integer i=Integer.valueOf(uri.substring(APP_VALUE_v2.length())); values.add(pf.newAttribute(TMPL_NS, VALUE2+i+"_"+count, TMPL_PREFIX, o.getValue(), o.getType())); } } count++; } set(entry1.getKey(),allvalues,values); } result.getAttributes().put(entity.getId(),allvalues); } } return result; } public void addVariableBindingsAsAttributeBindings() { Hashtable<QualifiedName, List<QualifiedName>> vb=getVariables(); for(Entry<QualifiedName,List<QualifiedName>> entry: vb.entrySet()) { int count=0; for (QualifiedName qn: entry.getValue()) { List<TypedValue> ll=new LinkedList<TypedValue>(); ll.add(pf.newAttribute(TMPL_NS, VALUE2+count+"_"+0, TMPL_PREFIX, qn, pf.getName().PROV_QUALIFIED_NAME)); count++; addAttribute(entry.getKey(),ll); } } } static public <E> void set(int pos, List<E> ll, E val) { int size=ll.size(); for (int i=size; i<=pos; i++) { ll.add(null); } ll.set(pos,val); } public void exportToJson(String filename) { BindingsBean bb=BindingsJson.toBean(this); BindingsJson.exportBean(filename,bb,true); } }