1 19 20 package org.apache.cayenne.access.util; 21 22 import java.util.ArrayList ; 23 import java.util.HashMap ; 24 import java.util.HashSet ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 import java.util.Set ; 29 30 import org.apache.cayenne.CayenneException; 31 import org.apache.cayenne.access.ResultIterator; 32 import org.apache.cayenne.map.DbAttribute; 33 import org.apache.cayenne.map.DbEntity; 34 35 46 public class DistinctResultIterator implements ResultIterator { 47 48 protected ResultIterator wrappedIterator; 49 protected Set fetchedIds; 50 protected Map nextDataRow; 51 protected DbEntity defaultEntity; 52 protected boolean compareFullRows; 53 54 protected boolean readingIds; 55 56 62 public DistinctResultIterator(ResultIterator wrappedIterator, DbEntity defaultEntity, 63 boolean compareFullRows) throws CayenneException { 64 if (wrappedIterator == null) { 65 throw new CayenneException("Null wrapped iterator."); 66 } 67 68 if (defaultEntity == null) { 69 throw new CayenneException("Null defaultEntity."); 70 } 71 72 this.wrappedIterator = wrappedIterator; 73 this.defaultEntity = defaultEntity; 74 this.fetchedIds = new HashSet (); 75 this.compareFullRows = compareFullRows; 76 77 checkNextRow(); 78 } 79 80 83 public void close() throws CayenneException { 84 wrappedIterator.close(); 85 } 86 87 90 public List dataRows(boolean close) throws CayenneException { 91 List list = new ArrayList (); 92 93 try { 94 while (this.hasNextRow()) { 95 list.add(this.nextDataRow()); 96 } 97 return list; 98 } 99 finally { 100 if (close) { 101 this.close(); 102 } 103 } 104 } 105 106 public int getDataRowWidth() { 107 return wrappedIterator.getDataRowWidth(); 108 } 109 110 public boolean hasNextRow() throws CayenneException { 111 return nextDataRow != null; 112 } 113 114 public Map nextDataRow() throws CayenneException { 115 if (!hasNextRow()) { 116 throw new CayenneException( 117 "An attempt to read uninitialized row or past the end of the iterator."); 118 } 119 120 Map row = nextDataRow; 121 checkNextRow(); 122 return row; 123 } 124 125 129 public Map nextObjectId(DbEntity entity) throws CayenneException { 130 if (!hasNextRow()) { 131 throw new CayenneException( 132 "An attempt to read uninitialized row or past the end of the iterator."); 133 } 134 135 Map row = nextDataRow; 136 137 if (!readingIds) { 139 Iterator it = row.entrySet().iterator(); 140 while (it.hasNext()) { 141 Map.Entry entry = (Map.Entry ) it.next(); 142 String name = (String ) entry.getKey(); 143 DbAttribute attribute = (DbAttribute) entity.getAttribute(name); 144 if (attribute == null || !attribute.isPrimaryKey()) { 145 it.remove(); 146 } 147 } 148 } 149 150 checkNextId(entity); 151 return row; 152 } 153 154 public void skipDataRow() throws CayenneException { 155 if (!hasNextRow()) { 156 throw new CayenneException( 157 "An attempt to read uninitialized row or past the end of the iterator."); 158 } 159 160 if (readingIds) { 161 checkNextId(defaultEntity); 162 } 163 else { 164 checkNextRow(); 165 } 166 } 167 168 void checkNextRow() throws CayenneException { 169 if (readingIds) { 170 throw new CayenneException( 171 "Can't go back from reading ObjectIds to reading rows."); 172 } 173 174 if (this.compareFullRows) { 175 checkNextUniqueRow(); 176 } 177 else { 178 checkNextRowWithUniqueId(); 179 } 180 } 181 182 void checkNextUniqueRow() throws CayenneException { 183 184 nextDataRow = null; 185 while (wrappedIterator.hasNextRow()) { 186 Map next = wrappedIterator.nextDataRow(); 187 188 if (fetchedIds.add(next)) { 189 this.nextDataRow = next; 190 break; 191 } 192 } 193 } 194 195 void checkNextRowWithUniqueId() throws CayenneException { 196 197 nextDataRow = null; 198 while (wrappedIterator.hasNextRow()) { 199 Map next = wrappedIterator.nextDataRow(); 200 201 205 Map id = new HashMap (); 206 Iterator it = defaultEntity.getPrimaryKey().iterator(); 207 while (it.hasNext()) { 208 DbAttribute pk = (DbAttribute) it.next(); 209 id.put(pk.getName(), next.get(pk.getName())); 210 } 211 212 if (fetchedIds.add(id)) { 213 this.nextDataRow = next; 214 break; 215 } 216 } 217 } 218 219 void checkNextId(DbEntity entity) throws CayenneException { 220 if (entity == null) { 221 throw new CayenneException("Null DbEntity, can't create id."); 222 } 223 224 this.readingIds = true; 225 this.nextDataRow = null; 226 227 while (wrappedIterator.hasNextRow()) { 228 Map next = wrappedIterator.nextObjectId(entity); 229 230 if (fetchedIds.add(next)) { 232 this.nextDataRow = next; 233 break; 234 } 235 } 236 } 237 } 238 | Popular Tags |