Class BaseTransform

java.lang.Object
org.eclipse.rdf4j.queryrender.sparql.ir.util.transform.BaseTransform
Direct Known Subclasses:
ApplyCollectionsTransform, ApplyNegatedPropertySetTransform, ApplyNormalizeGraphInnerPathsTransform, ApplyPathsFixedPointTransform, ApplyPathsTransform, CanonicalizeBareNpsOrientationTransform, CanonicalizeGroupedTailStepTransform, CanonicalizeNpsByProjectionTransform, CanonicalizeUnionBranchOrderTransform, CoalesceAdjacentGraphsTransform, FlattenSingletonUnionsTransform, FuseAltInverseTailBGPTransform, FusePathPlusTailAlternationUnionTransform, FusePrePathThenUnionAlternationTransform, FuseServiceNpsUnionLateTransform, FuseUnionOfNpsBranchesTransform, FuseUnionOfPathTriplesPartialTransform, FuseUnionOfSimpleTriplesTransform, GroupFilterExistsWithPrecedingTriplesTransform, GroupUnionOfSameGraphBranchesTransform, GroupValuesAndNpsInUnionBranchTransform, LiftPathUnionScopeInsideGraphTransform, MergeAdjacentValuesTransform, MergeFilterExistsIntoPrecedingGraphTransform, MergeOptionalIntoPrecedingGraphTransform, NormalizeFilterNotInTransform, NormalizeNpsMemberOrderTransform, NormalizeZeroOrOneSubselectTransform, ReorderFiltersInOptionalBodiesTransform, SimplifyPathParensTransform, UnwrapSingleBgpInUnionBranchesTransform

public class BaseTransform extends Object
Shared helpers and small utilities for IR transform passes. Conventions and invariants: - Transforms are functional: they do not mutate input nodes; instead they build new IR blocks as needed. - Path/chain fusions are conservative and only cross intermediate variables that the parser created for property paths (variable names prefixed with _anon_path_). This prevents accidental elimination or inversion of user-defined variables. - Text helpers respect property path precedence and add parentheses only when required for correctness. - Container nodes (GRAPH/OPTIONAL/MINUS/UNION/SERVICE) are preserved, and recursion uses transformChildren to keep transform code small and predictable.
  • Field Details

  • Constructor Details

    • BaseTransform

      public BaseTransform()
  • Method Details

    • isConstantIriPredicate

      public static boolean isConstantIriPredicate(IrStatementPattern sp)
      Convenience: true iff SP has a constant-IRI predicate.
    • iri

      public static String iri(Var pred, TupleExprIRRenderer r)
      Convenience: render a constant-IRI predicate Var to text. Returns null if not a constant IRI.
    • normalizeCompactNps

      public static String normalizeCompactNps(String path)
      Normalize compact negated-property-set forms into the canonical parenthesized variant. Examples: "!ex:p" -> "!(ex:p)", "!^ex:p" -> "!(^ex:p)". Leaves already-canonical and non-NPS text unchanged.
    • mergeNpsMembers

      public static String mergeNpsMembers(String a, String b)
      Merge NPS members of two canonical strings '!(...)', returning '!(a|b)'. Falls back to 'a' when malformed.
    • unionIsExplicitAndAllBranchesScoped

      public static boolean unionIsExplicitAndAllBranchesScoped(IrUnion u)
      Universal safeguard for explicit user UNIONs: true iff the UNION is marked as new scope and all its branches are also marked as new scope. Such a UNION should never be fused into a single path expression.
    • rewriteContainers

      public static IrNode rewriteContainers(IrNode n, Function<IrBGP,IrBGP> f)
      Utility: rewrite container nodes by applying a given function to their inner IrBGP children. Non-container nodes are returned unchanged. This abstracts common recursion boilerplate across many transforms and ensures newScope and other flags are preserved consistently for containers. Containers handled: IrGraph, IrOptional, IrMinus, IrService, IrUnion. Nested IrBGP lines that appear directly inside a parent IrBGP (explicit grouping) are intentionally left unchanged here — transforms should decide if and how to recurse into such explicit groups.
    • bgpWithLines

      public static IrBGP bgpWithLines(IrBGP original, List<IrNode> lines)
      Build a new IrBGP with the same scope flag and the provided lines.
    • copyAllExcept

      public static void copyAllExcept(IrBGP from, IrBGP to, IrNode except)
    • fuseAdjacentPtThenPt

      public static IrBGP fuseAdjacentPtThenPt(IrBGP bgp)
      Fuse adjacent IrPathTriple nodes when the first's object equals the second's subject.
    • fusePtSpPtSequence

      public static IrBGP fusePtSpPtSequence(IrBGP bgp, TupleExprIRRenderer r)
      Fuse a three-line sequence: IrPathTriple (A), IrStatementPattern (B), IrPathTriple (C) into A then ( ^B.p / C ). Pattern constraints: - A.object equals B.object (inverse join candidate) and A.object is an _anon_path_* var. - B.subject equals C.subject and both B.subject and B.object are _anon_path_* vars.
    • orientBareNpsForNext

      public static IrBGP orientBareNpsForNext(IrBGP bgp)
      Re-orient a bare negated property set path "!(...)" so that its object matches the subject of the immediately following triple when possible, enabling chaining: prefer s !(...) ?x when the next line starts with ?x ...
    • fuseAdjacentSpThenPt

      public static IrBGP fuseAdjacentSpThenPt(IrBGP bgp, TupleExprIRRenderer r)
    • joinPathWithLaterSp

      public static IrBGP joinPathWithLaterSp(IrBGP bgp, TupleExprIRRenderer r)
    • sameVar

      public static boolean sameVar(Var a, Var b)
    • sameVarOrValue

      public static boolean sameVarOrValue(Var a, Var b)
      True when both variables denote the same term: compares names if both are variables without value, or compares values if both are constants. Returns false when one has a value and the other does not.
    • isAnonPathVar

      public static boolean isAnonPathVar(Var v)
    • isAnonPathInverseVar

      public static boolean isAnonPathInverseVar(Var v)
      True when the anonymous path var explicitly encodes inverse orientation.
    • branchHasAnonPathBridge

      public static boolean branchHasAnonPathBridge(IrBGP branch)
      True if the given branch contains at least one variable with the parser-generated _anon_path_ (or inverse variant) prefix anywhere in its simple triple-like structures. Used as a safety valve to allow certain fusions across UNION branches that were marked as introducing a new scope in the algebra: if every branch contains an anonymous path bridge var, the fusion is considered safe and preserves user-visible bindings.
    • unionBranchesAllHaveAnonPathBridge

      public static boolean unionBranchesAllHaveAnonPathBridge(IrUnion u)
      True if all UNION branches contain at least one _anon_path_* variable (or inverse variant). Rationale: when there is no explicit UNION scope, this safety gate ensures branch bodies are derived from path-decoding internals rather than user variables, so fusing to an alternation/NPS preserves semantics.
    • unionBranchesShareCommonAnonPathVarName

      public static boolean unionBranchesShareCommonAnonPathVarName(IrUnion u)
      True if all UNION branches share at least one common variable name that starts with the _anon_path_ prefix. The check descends into simple triple-like structures and container blocks. Rationale: used for the special-case where a UNION is marked as a new variable scope but still eligible for merging — only when we can prove the scope originates from a shared parser-generated bridge variable rather than a user variable. This keeps merges conservative and avoids collapsing distinct user bindings.
    • unionBranchesShareAnonPathVarWithAllowedRoleMapping

      public static boolean unionBranchesShareAnonPathVarWithAllowedRoleMapping(IrUnion u)
      New-scope UNION safety: true iff the two UNION branches share at least one _anon_path_* variable name. Implementation uses the IR getVars() API to collect all Vars from each branch (including nested nodes) and then checks for intersection on names that start with the parser bridge prefixes. This captures subject/object, predicate vars, as well as IrPathTriple.pathVars contributed during path rewrites.
    • invertNegatedPropertySet

      public static String invertNegatedPropertySet(String npsText)
      If the given path text is a negated property set of the form !(a|b|...), return a version where each member is inverted by toggling the leading '^' (i.e., a -> ^a, ^a -> a). Returns null when the input is not a simple NPS.
    • fuseAltInverseTailBGP

      public static IrBGP fuseAltInverseTailBGP(IrBGP bgp, TupleExprIRRenderer r)
      Fuse a path triple whose object is a bridge var with a constant-IRI tail triple that also uses the bridge var, producing a new path with an added '/^p' or '/p' segment. This version indexes join candidates and works inside GRAPH bodies as well. It is conservative: only constant predicate tails are fused and containers are preserved.
    • varOrValue

      public static String varOrValue(Var v, TupleExprIRRenderer r)