private static void addPathsToLeaves(Query tree, List<Filter[]> workingPath, List<List<Filter>> results) { if (tree.getSubTrees().isEmpty()) { //this is the leaf List<Filter> pathToLeaf = new ArrayList<>(); Consumer<Filter> addOps = (f) -> { if (!(f instanceof NoopFilter)) { pathToLeaf.add(f); } }; for (Filter[] fs : workingPath) { Arrays.asList(fs).forEach(addOps); } Arrays.asList(filters(tree.getFragments())).forEach(addOps); results.add(pathToLeaf); } else { workingPath.add(filters(tree.getFragments())); for (Query subTree : tree.getSubTrees()) { addPathsToLeaves(subTree, workingPath, results); } workingPath.remove(workingPath.size() - 1); } }
@Override public final void initialize(Configuration configuration) { this.backend = doInitialize(configuration); tenantContext = new TraversalContext<>(this, Query.empty(), Query.path().with(With.type(Tenant.class)).get(), backend, Tenant.class, configuration, observableContext, transactionConstructor); relationshipContext = new TraversalContext<>(this, Query.empty(), Query.path().get(), backend, Relationship.class, configuration, observableContext, transactionConstructor); this.configuration = configuration; }
private void addToString(StringBuilder bld, int indentation) { indent(bld, indentation); bld.append("Query[fragments=").append(Arrays.toString(fragments)); if (!subTrees.isEmpty()) { bld.append("\n"); subTrees.forEach((s) -> { s.addToString(bld, indentation + 1); bld.append("\n"); }); indent(bld, indentation); } bld.append("]"); }
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Query that = (Query) o; return Arrays.equals(this.getFragments(), that.getFragments()) && this.getSubTrees().equals(that.getSubTrees()); }
@SuppressWarnings({"ConstantConditions", "unchecked"}) public static Query to(CanonicalPath entity) { return Query.path().with(With.path(entity)).get(); }
private void createCustomRelationships(BE entity, Relationships.Direction direction, Map<String, Set<CanonicalPath>> otherEnds, Transaction<BE> tx) { otherEnds.forEach((name, ends) -> ends.forEach((end) -> { try { BE endObject = tx.find(end); BE from = direction == outgoing ? entity : endObject; BE to = direction == outgoing ? endObject : entity; EntityAndPendingNotifications<BE, Relationship> res = Util.createAssociation(tx, from, name, to, null); tx.getPreCommit().addNotifications(res); } catch (ElementNotFoundException e) { throw new EntityNotFoundException(Query.filters(Query.to(end))); } })); } }
public Read(TraversalContext<BE, Relationship> context) { super(context); QueryFragment[] filters = context.selectCandidates.getFragments(); if (filters.length == 0) { direction = Relationships.Direction.outgoing; } else { direction = ((SwitchElementType) filters[filters.length - 1].getFilter()).getDirection(); } }
public static <BE> BE getSingle(Transaction<BE> backend, Query query, SegmentType entityType) { BE result = backend.querySingle(query); if (result == null) { throw new EntityNotFoundException(entityType, Query.filters(query)); } return result; }
public Builder with(Query other, Function<Filter, QueryFragment> converter) { with(converter, other.fragments); for (Query sub : other.getSubTrees()) { branch().with(sub, converter).done(); } return this; }
/** * @return a new query selecting the select candidates from the source path. The resulting extender * is set up to append filter fragments. */ Query.SymmetricExtender select() { return sourcePath.extend().filter().withExact(selectCandidates); }
@SuppressWarnings("unchecked") public static Query queryTo(Query sourcePath, Path path) { if (path instanceof CanonicalPath) { return Query.to((CanonicalPath) path); } else { Query.SymmetricExtender extender = sourcePath.extend().path(); extender.with(With.relativePath(null, (RelativePath) path)); return extender.get(); } }
/** * If the current position in the traversal defines any select candidates, the new context will have its source path * composed by appending the select candidates to the current source path. * * @return a context builder with the modified source path */ Builder<BE, E> proceed() { return new Builder<>(this, hop(), Query.filter(), entityClass); }
@Override protected String getProposedId(Transaction<BE> tx, Feed.Blueprint blueprint) { BE tenant = tx.querySingle(context.sourcePath.extend().filter() .with(type(Tenant.class)).get()); if (tenant == null) { throw new EntityNotFoundException(Tenant.class, Query.filters(context.sourcePath)); } CanonicalPath feedPath = tx.extractCanonicalPath(tenant) .extend(Feed.SEGMENT_TYPE, blueprint.getId()).get(); return context.configuration.getFeedIdStrategy().generate(context.inventory.keepTransaction(tx), new Feed(feedPath, null, null, null)); }
/** * @return a new symmetric builder initialized with this query */ public SymmetricExtender extend() { return new SymmetricExtender(asBuilder()); }
@Override public String toString() { StringBuilder bld = new StringBuilder(); addToString(bld, 0); return bld.toString(); }
/** * Constructs a new traversal context by replacing the source path with the provided query and clearing out the * selected candidates. * * @param path the source path of the new context * @return a new traversal context with the provided source path and empty select candidates, but otherwise * identical to this one. */ TraversalContext<BE, E> replacePath(Query path) { return new TraversalContext<>(inventory, path, Query.empty(), backend, entityClass, configuration, observableContext, transactionRetries, this, null, transactionConstructor); }
/** * Converts the provided filter tree to a list of paths (array of filters). Each of the paths in the result * represent 1 branch from the tree from root to some leaf. * * @param query the tree of filters * @return the list of paths */ public static Filter[][] filters(Query query) { List<List<Filter>> paths = new ArrayList<>(); List<Filter[]> workingPath = new ArrayList<>(); addPathsToLeaves(query, workingPath, paths); Filter[][] ret = new Filter[paths.size()][]; Arrays.setAll(ret, (i) -> paths.get(i).toArray(new Filter[paths.get(i).size()])); return ret; }
@Override protected void preCreate(OperationType.Blueprint blueprint, Transaction<BE> tx) { //disallow this if the parent resource type is a part of a metadata pack if (tx.traverseToSingle(getParent(tx), Query.path().with(asTargetBy(incorporates), With.type(MetadataPack.class)).get()) != null) { throw new IllegalArgumentException("Cannot create an operation type of resource type included in " + "a meta data pack. This would invalidate the metadata pack's identity."); } }