001package org.biojava.bio.annodb; 002 003import java.util.ArrayList; 004import java.util.Iterator; 005import java.util.List; 006import java.util.NoSuchElementException; 007 008import org.biojava.bio.AnnotationTools; 009import org.biojava.bio.AnnotationType; 010 011/** 012 * <p>An AnnotationDB that provides a merged view of a list of underlying DBs.</p> 013 * 014 * @author Matthew Pocock 015 * @since 1.3 016 */ 017public class MergingAnnotationDB implements AnnotationDB { 018 private final String name; 019 private final List merged; 020 021 /** 022 * Create a new MergingAnnotationDB with a name and no DBs to merge. 023 * 024 * @param name the name of this DB 025 */ 026 public MergingAnnotationDB(String name) { 027 this.name = name; 028 this.merged = new ArrayList(); 029 } 030 031 /** 032 * Create a new MergingAnnotationDB with a name and a list of DBs to merge. 033 * 034 * @param name the name of this DB 035 * @param merged a list of DBs to merge 036 */ 037 public MergingAnnotationDB(String name, List merged) { 038 this.name = name; 039 this.merged = new ArrayList(merged); 040 } 041 042 /** 043 * Add a DB to be merged in this view. 044 * 045 * @param toAdd the AnnotationDB to add 046 */ 047 public void addAnnotationDB(AnnotationDB toAdd) { 048 if(!merged.contains(toAdd)) { 049 merged.add(toAdd); 050 } 051 } 052 053 /** 054 * Remove a DB from this view. 055 * 056 * @param toRemove the AnnotationDB to remove 057 */ 058 public void removeAnnotationDB(AnnotationDB toRemove) { 059 merged.remove(toRemove); 060 } 061 062 /** 063 * Return a list of merged DBs. This can be modified independantly of this DB. 064 * 065 * @return a List of merged DBs 066 */ 067 public List getMerged() { 068 return new ArrayList(merged); 069 } 070 071 public String getName() { 072 return name; 073 } 074 075 public AnnotationType getSchema() { 076 AnnotationType schema = AnnotationType.NONE; 077 078 for(Iterator i = merged.iterator(); i.hasNext(); ) { 079 AnnotationDB db = (AnnotationDB) i.next(); 080 schema = AnnotationTools.union(schema, db.getSchema()); 081 } 082 083 return schema; 084 } 085 086 public Iterator iterator() { 087 return new Iterator() { 088 Iterator ii; 089 Iterator ci; 090 Object item; 091 092 { 093 ii = merged.iterator(); 094 EVERYTHING: 095 while(item == null) { 096 if(ii.hasNext()) { 097 AnnotationDB adb = (AnnotationDB) ii.next(); 098 ci = adb.iterator(); 099 if(ci.hasNext()) { 100 item = ci.next(); 101 } 102 } else { 103 break EVERYTHING; 104 } 105 } 106 } 107 108 public boolean hasNext() { 109 return item != null; 110 } 111 112 public Object next() { 113 Object it = item; 114 item = _next(); 115 return it; 116 } 117 118 private Object _next() { 119 while(!ci.hasNext()) { 120 if(ii.hasNext()) { 121 AnnotationDB adb = (AnnotationDB) ii.next(); 122 ci = adb.iterator(); 123 } else { 124 return null; 125 } 126 } 127 128 return ci.next(); 129 } 130 131 public void remove() { 132 throw new NoSuchElementException(); 133 } 134 }; 135 } 136 137 public int size() { 138 int size = 0; 139 140 for(Iterator dbi = merged.iterator(); dbi.hasNext(); ) { 141 size += ((AnnotationDB) dbi.next()).size(); 142 } 143 144 return size; 145 } 146 147 public AnnotationDB filter(AnnotationType at) { 148 List anns = new ArrayList(); 149 150 for(Iterator i = merged.iterator(); i.hasNext(); ) { 151 AnnotationDB adb = (AnnotationDB) i.next(); 152 AnnotationDB res = adb.filter(at); 153 if(res.size() > 0) { 154 anns.add(res); 155 } 156 } 157 158 if(anns.isEmpty()) { 159 return AnnotationDB.EMPTY; 160 } else if(anns.size() == 1) { 161 return (AnnotationDB) anns.get(0); 162 } else { 163 return new MergingAnnotationDB("", anns); 164 } 165 } 166 167 public AnnotationDB search(AnnotationType at) { 168 List anns = new ArrayList(); 169 170 for(Iterator i = merged.iterator(); i.hasNext(); ) { 171 AnnotationDB adb = (AnnotationDB) i.next(); 172 AnnotationDB res = adb.search(at); 173 if(res.size() > 0) { 174 anns.add(res); 175 } 176 } 177 178 if(anns.isEmpty()) { 179 return AnnotationDB.EMPTY; 180 } else if(anns.size() == 1) { 181 return (AnnotationDB) anns.get(0); 182 } else { 183 return new MergingAnnotationDB("", anns); 184 } 185 } 186} 187