1 19 20 package org.apache.cayenne.access; 21 22 import java.util.ArrayList ; 23 import java.util.Arrays ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 import java.util.TreeMap ; 29 30 import org.apache.cayenne.CayenneRuntimeException; 31 import org.apache.cayenne.DataRow; 32 import org.apache.cayenne.Persistent; 33 import org.apache.cayenne.access.jdbc.ColumnDescriptor; 34 import org.apache.cayenne.exp.Expression; 35 import org.apache.cayenne.exp.parser.ASTPath; 36 import org.apache.cayenne.map.DbAttribute; 37 import org.apache.cayenne.map.DbJoin; 38 import org.apache.cayenne.map.DbRelationship; 39 import org.apache.cayenne.map.ObjAttribute; 40 import org.apache.cayenne.map.ObjRelationship; 41 import org.apache.cayenne.query.PrefetchTreeNode; 42 43 49 class PrefetchProcessorJointNode extends PrefetchProcessorNode { 50 51 ColumnDescriptor[] columns; 52 int[] idIndices; 53 int rowCapacity; 54 Map resolved; 55 List resolvedRows; 56 57 PrefetchProcessorJointNode(PrefetchTreeNode parent, String segmentPath) { 58 super(parent, segmentPath); 59 } 60 61 void afterInit() { 62 super.afterInit(); 63 64 66 int capacity = dataRows != null ? dataRows.size() : 10; 69 if (capacity > 100) { 70 capacity = capacity / 2; 71 } 72 73 objects = new ArrayList (capacity); 74 resolved = new HashMap (capacity); 75 resolvedRows = new ArrayList (capacity); 76 buildRowMapping(); 77 buildPKIndex(); 78 } 79 80 List getResolvedRows() { 81 return resolvedRows; 82 } 83 84 void addObject(Persistent object, DataRow row) { 85 objects.add(object); 86 resolvedRows.add(row); 87 } 88 89 92 Map idFromFlatRow(DataRow flatRow) { 93 94 98 Map id = new TreeMap (); 99 for (int i = 0; i < idIndices.length; i++) { 100 Object value = flatRow.get(columns[idIndices[i]].getLabel()); 101 id.put(columns[idIndices[i]].getName(), value); 102 } 103 104 return id; 105 } 106 107 111 Persistent getResolved(Map id) { 112 return (Persistent) resolved.get(id); 113 } 114 115 119 void putResolved(Map id, Persistent object) { 120 resolved.put(id, object); 121 } 122 123 126 DataRow rowFromFlatRow(DataRow flatRow) { 127 DataRow row = new DataRow(rowCapacity); 128 129 for (int i = 0; i < columns.length; i++) { 131 row.put(columns[i].getName(), flatRow.get(columns[i].getLabel())); 132 } 133 134 return row; 135 } 136 137 140 143 private void buildRowMapping() { 144 Map targetSource = new TreeMap (); 145 146 PrefetchTreeNode jointRoot = this; 148 while (jointRoot.getParent() != null && !jointRoot.isDisjointPrefetch()) { 149 jointRoot = jointRoot.getParent(); 150 } 151 152 String prefix; 153 if (jointRoot != this) { 154 Expression objectPath = Expression.fromString(getPath(jointRoot)); 155 ASTPath translated = (ASTPath) ((PrefetchProcessorNode) jointRoot) 156 .getResolver() 157 .getEntity() 158 .translateToDbPath(objectPath); 159 160 prefix = translated.getOperand(0) + "."; 162 } 163 else { 164 prefix = ""; 165 } 166 167 170 if (getParent() != null 171 && !getParent().isPhantom() 172 && getIncoming() != null 173 && !getIncoming().getRelationship().isFlattened()) { 174 175 DbRelationship r = (DbRelationship) getIncoming() 176 .getRelationship() 177 .getDbRelationships() 178 .get(0); 179 Iterator it = r.getJoins().iterator(); 180 while (it.hasNext()) { 181 DbJoin join = (DbJoin) it.next(); 182 183 PrefetchProcessorNode parent = (PrefetchProcessorNode) getParent(); 184 String source; 185 if (parent instanceof PrefetchProcessorJointNode) { 186 source = ((PrefetchProcessorJointNode) parent).sourceForTarget(join 187 .getSourceName()); 188 } 189 else { 190 source = join.getSourceName(); 191 } 192 193 if (source == null) { 194 throw new CayenneRuntimeException( 195 "Propagated column value is not configured for parent node. Join: " 196 + join); 197 } 198 199 appendColumn(targetSource, join.getTargetName(), source); 200 } 201 } 202 203 Iterator attributes = getResolver().getEntity().getAttributes().iterator(); 205 while (attributes.hasNext()) { 206 ObjAttribute attribute = (ObjAttribute) attributes.next(); 207 String target = attribute.getDbAttributePath(); 208 209 appendColumn(targetSource, target, prefix + target); 210 } 211 212 Iterator relationships = getResolver().getEntity().getRelationships().iterator(); 214 while (relationships.hasNext()) { 215 ObjRelationship rel = (ObjRelationship) relationships.next(); 216 DbRelationship dbRel = (DbRelationship) rel.getDbRelationships().get(0); 217 Iterator dbAttributes = dbRel.getSourceAttributes().iterator(); 218 219 while (dbAttributes.hasNext()) { 220 DbAttribute attribute = (DbAttribute) dbAttributes.next(); 221 String target = attribute.getName(); 222 223 appendColumn(targetSource, target, prefix + target); 224 } 225 } 226 227 Iterator pks = getResolver().getEntity().getDbEntity().getPrimaryKey().iterator(); 229 while (pks.hasNext()) { 230 DbAttribute pk = (DbAttribute) pks.next(); 231 appendColumn(targetSource, pk.getName(), prefix + pk.getName()); 232 } 233 234 int size = targetSource.size(); 235 this.rowCapacity = (int) Math.ceil(size / 0.75); 236 this.columns = new ColumnDescriptor[size]; 237 targetSource.values().toArray(columns); 238 } 239 240 private ColumnDescriptor appendColumn(Map map, String name, String label) { 241 ColumnDescriptor column = (ColumnDescriptor) map.get(name); 242 243 if (column == null) { 244 column = new ColumnDescriptor(); 245 column.setName(name); 246 column.setLabel(label); 247 map.put(name, column); 248 } 249 250 return column; 251 } 252 253 256 private void buildPKIndex() { 257 List pks = getResolver().getEntity().getDbEntity().getPrimaryKey(); 259 this.idIndices = new int[pks.size()]; 260 261 Arrays.fill(idIndices, -1); 263 264 for (int i = 0; i < idIndices.length; i++) { 265 DbAttribute pk = (DbAttribute) pks.get(i); 266 267 for (int j = 0; j < columns.length; j++) { 268 if (pk.getName().equals(columns[j].getName())) { 269 idIndices[i] = j; 270 break; 271 } 272 } 273 274 if (idIndices[i] == -1) { 276 throw new CayenneRuntimeException("PK column is not part of result row: " 277 + pk.getName()); 278 } 279 } 280 } 281 282 285 private String sourceForTarget(String targetColumn) { 286 if (targetColumn != null && columns != null) { 287 for (int i = 0; i < columns.length; i++) { 288 if (targetColumn.equals(columns[i].getName())) { 289 return columns[i].getLabel(); 290 } 291 } 292 } 293 294 return null; 295 } 296 297 } 298 | Popular Tags |