private PrefetchTreeNode deepClone(PrefetchTreeNode source, PrefetchTreeNode targetParent) { PrefetchTreeNode target = new PrefetchTreeNode(targetParent, source.getName()); target.setEjbqlPathEntityId(source.getEjbqlPathEntityId()); target.setEntityName(source.getEntityName()); target.setPhantom(source.isPhantom()); target.setSemantics(source.getSemantics()); for (PrefetchTreeNode child : source.getChildren()) { target.addChild(deepClone(child, target)); } return target; }
/** * Creates and returns a prefetch tree spanning a single path. The tree is * made of phantom nodes, up to the leaf node, which is non-phantom and has * specified semantics. * * @since 4.0 */ public static PrefetchTreeNode withPath(String path, int semantics) { PrefetchTreeNode root = new PrefetchTreeNode(); PrefetchTreeNode node = root.addPath(path); node.setPhantom(false); node.setSemantics(semantics); return root; }
/** * Returns full prefetch path, that is a dot separated String of node names * starting from root and up to and including this node. Note that root * "name" is considered to be an empty string. */ public String getPath() { return getPath(null); }
/** * Adds a joint prefetch. * * @since 4.0 */ void mergePrefetch(PrefetchTreeNode node) { if (prefetchTree == null) { prefetchTree = new PrefetchTreeNode(); } prefetchTree.merge(node); }
private PrefetchTreeNode cloneJointSubtree(PrefetchTreeNode parent) { PrefetchTreeNode cloned = new PrefetchTreeNode(parent, getName()); if (parent != null) { cloned.setSemantics(getSemantics()); cloned.setPhantom(isPhantom()); } if (children != null) { for (PrefetchTreeNode child : children) { if (child.isJointPrefetch()) { cloned.addChild(child.cloneJointSubtree(cloned)); } } } return cloned; }
void merge(PrefetchTreeNode original, PrefetchTreeNode toMerge) { if (toMerge.getSemantics() != UNDEFINED_SEMANTICS) { original.setSemantics(toMerge.getSemantics()); } if (!toMerge.isPhantom()) { original.setPhantom(false); } for (PrefetchTreeNode childToMerge : toMerge.getChildren()) { PrefetchTreeNode childOrigin = original.getChild(childToMerge.getName()); if (childOrigin == null) { childOrigin = original.addPath(childToMerge.getName()); } merge(childOrigin, childToMerge); } }
protected PrefetchProcessorNode toResultsTree(ClassDescriptor descriptor, PrefetchTreeNode prefetchTree, List<Object[]> rows, int position) { List<DataRow> rowsColumn = new ArrayList<>(rows.size()); for (Object[] row : rows) { rowsColumn.add((DataRow) row[position]); } if (prefetchTree != null) { PrefetchTreeNode prefetchTreeNode = null; for (PrefetchTreeNode prefetch : prefetchTree.getChildren()) { if (descriptor.getEntity().getName().equals(prefetch.getEntityName())) { if (prefetchTreeNode == null) { prefetchTreeNode = new PrefetchTreeNode(); } PrefetchTreeNode addPath = prefetchTreeNode.addPath(prefetch.getPath()); addPath.setSemantics(prefetch.getSemantics()); addPath.setPhantom(false); } } prefetchTree = prefetchTreeNode; } if (prefetchTree == null) { return new ObjectResolver(context, descriptor, metadata.isRefreshingObjects()) .synchronizedRootResultNodeFromDataRows(rowsColumn); } else { HierarchicalObjectResolver resolver = new HierarchicalObjectResolver(context, metadata, descriptor, true); return resolver.synchronizedRootResultNodeFromDataRows(prefetchTree, rowsColumn, prefetchResultsByPath); } }
@Override public void writeTo(Output output, PrefetchTreeNode message) throws IOException { if (message.getName() != null) { output.writeString(1, message.getName(), false); } output.writeBool(2, message.isPhantom(), false); output.writeInt32(3, message.getSemantics(), false); if (message.getEjbqlPathEntityId() != null) { output.writeString(4, message.getEjbqlPathEntityId(), false); } if (message.getEntityName() != null) { output.writeString(5, message.getEntityName(), false); } if (message.hasChildren()) { for (PrefetchTreeNode node : message.getChildren()) { output.writeObject(6, node, this, true); } } }
/** * Merges a prefetch path with specified semantics into the query prefetch * tree. * * @return this object */ public ColumnSelect<T> prefetch(String path, int semantics) { if (path == null) { return this; } if (prefetches == null) { prefetches = new PrefetchTreeNode(); } prefetches.addPath(path).setSemantics(semantics); replacementQuery = null; return this; }
/** * Removes or makes phantom a node defined by this path. If the node for this path * doesn't have any children, it is removed, otherwise it is made phantom. */ public void removePath(String path) { PrefetchTreeNode node = getNode(path); while (node != null) { if (node.children != null) { node.setPhantom(true); break; } String segment = node.getName(); node = node.getParent(); if (node != null) { node.removeChild(segment); } } }
switch (number) { case 0: message.readResolve(); return; case 1: break; case 2: message.setPhantom(input.readBool()); break; case 3: message.setSemantics(input.readInt32()); break; case 4: message.setEjbqlPathEntityId(input.readString()); break; case 5: message.setEntityName(input.readString()); break; case 6:
/** * Traverses the tree depth-first, invoking callback methods of the * processor when passing through the nodes. */ public void traverse(PrefetchProcessor processor) { boolean result = false; if (isPhantom()) { result = processor.startPhantomPrefetch(this); } else if (isDisjointPrefetch()) { result = processor.startDisjointPrefetch(this); } else if (isDisjointByIdPrefetch()) { result = processor.startDisjointByIdPrefetch(this); } else if (isJointPrefetch()) { result = processor.startJointPrefetch(this); } else { result = processor.startUnknownPrefetch(this); } // process children unless processing is blocked... if (result && children != null) { for (PrefetchTreeNode child : children) { child.traverse(processor); } } // call finish regardless of whether children were processed processor.finishPrefetch(this); }
PrefetchProcessorNode processorNode = (PrefetchProcessorNode) node; if (node.getParent().isPhantom()) { currentQuery = new PrefetchSelectQuery(node.getPath(), relationship); queries.add(currentQuery); qualifiersCount = 0; PrefetchTreeNode jointSubtree = node.cloneJointSubtree(); if (jointSubtree.hasChildren()) { query.setPrefetchTree(jointSubtree);
private void appendPrefetches(PrefetchTreeNode root, ResourceEntity<?> entity, int prefetchSemantics) { for (Map.Entry<String, ResourceEntity<?>> e : entity.getChildren().entrySet()) { // skip prefetches of non-persistent entities if (e.getValue().getAgEntity() instanceof AgPersistentEntity) { PrefetchTreeNode child = root.addPath(e.getKey()); // always full prefetch related entities... we can't use phantom // as this will hit object cache and hence won't be cache // controlled via query cache anymore... child.setPhantom(false); child.setSemantics(prefetchSemantics); appendPrefetches(child, e.getValue(), prefetchSemantics); } } if (entity.getMapBy() != null) { appendPrefetches(root, entity.getMapBy(), prefetchSemantics); } } }
/** * Adds a "path" with specified semantics to this prefetch node. All yet * non-existent nodes in the created path will be marked as phantom. * * @return the last segment in the created path. */ public PrefetchTreeNode addPath(String path) { if (Util.isEmptyString(path)) { throw new IllegalArgumentException("Empty path: " + path); } PrefetchTreeNode node = this; StringTokenizer toks = new StringTokenizer(path, Entity.PATH_SEPARATOR); while (toks.hasMoreTokens()) { String segment = toks.nextToken(); PrefetchTreeNode child = node.getChild(segment); if (child == null) { child = new PrefetchTreeNode(node, segment); node.addChild(child); } node = child; } return node; }
for(PrefetchTreeNode prefetch : query.getPrefetchTree().getChildren()) { prefetch.setEntityName(oe.getName()); for (PrefetchTreeNode prefetch : query.getPrefetchTree().adjacentJointNodes()) { Expression prefetchExp = ExpressionFactory.exp(prefetch.getPath()); ASTDbPath dbPrefetch = (ASTDbPath) oe.translateToDbPath(prefetchExp);
private void addPrefetchedColumnsIfAny(final String visitedIdentifier) { PrefetchTreeNode prefetchTree = context.getCompiledExpression().getPrefetchTree(); if (prefetchTree != null) { for (PrefetchTreeNode prefetch : prefetchTree.adjacentJointNodes()) { ClassDescriptor descriptor = context.getEntityDescriptor(prefetch.getEjbqlPathEntityId()); if (visitedIdentifier.equals(prefetch.getEjbqlPathEntityId())) { DbEntity table = descriptor.getRootDbEntities().iterator().next(); ObjEntity objectEntity = descriptor.getEntity(); prefetch.setEntityName(objectEntity.getName()); Expression prefetchExp = ExpressionFactory.exp(prefetch.getPath()); Expression dbPrefetch = objectEntity.translateToDbPath(prefetchExp); DbRelationship r = null; for (PathComponent<DbAttribute, DbRelationship> component : table.resolvePath(dbPrefetch, context .getMetadata().getPathSplitAliases())) { r = component.getRelationship(); } if (r == null) { throw new CayenneRuntimeException("Invalid joint prefetch '%s' for entity: %s" , prefetch, objectEntity.getName()); } for (DbAttribute attribute : r.getTargetEntity().getAttributes()) { appendColumn(prefetch.getEjbqlPathEntityId() + "." + prefetch.getPath(), attribute, "", prefetch.getPath() + "." + attribute.getName(), null); } } } } }
public void addChild(PrefetchTreeNode child) { if (Util.isEmptyString(child.getName())) { throw new IllegalArgumentException("Child has no segmentPath: " + child); } if (child.getParent() != this) { child.getParent().removeChild(child.getName()); child.parent = this; } if (children == null) { children = new ArrayList(4); } children.add(child); }
/** * Merges {@link PrefetchTreeNode} into the current prefetch tree, cloning * the nodes added to this tree. Merged nodes semantics (if defined) and * non-phantom status are applied to the nodes of this tree. * * @param node * a root node of a tree to merge into this tree. The path of the * merged node within the resulting tree is determined from its * name. * * @since 4.0 */ public void merge(PrefetchTreeNode node) { if (node == null) { throw new NullPointerException("Null node"); } PrefetchTreeNode start = node.getName() != null ? addPath(node.getName()) : this; merge(start, node); }
while (jointRoot.getParent() != null && !jointRoot.isDisjointPrefetch() && !jointRoot.isDisjointByIdPrefetch()) { jointRoot = jointRoot.getParent(); && !getParent().isPhantom() && getIncoming() != null && !getIncoming().getRelationship().isFlattened()) {