Mapper

Builds one document from another. The generator only translates the narrowest case, a bare variable-to-variable copy, and even then drops the source field path; everything else becomes a bean call the rule does not write.

Translated com.tibco.plugin.mapper.MapperActivity

What it does in BusinessWorks

Builds one document from another: process data in, an activity’s input schema out. Under the Designer canvas it is XSLT, but what lands in the .process file is the same mechanism every other activity uses for its input mapping, pd:inputBindings, one <xsl:value-of select="..."> per output field. A Mapper activity is not structurally different from any other activity’s input mapping; it just has no engine call beyond passing the shape it built to whatever comes next, and it usually has more bindings than a typical activity because building a document is its entire job.

The Camel equivalent

BusinessWorks 5.process
<pd:activity name="Build Order Summary">
  <pd:type>com.tibco.plugin.mapper
    .MapperActivity
  </pd:type>
  <pd:inputBindings>
    <CustomerId>
      <xsl:value-of
        select="$Order/CustomerId"/>
    </CustomerId>
    <OrderTotal>
      <xsl:value-of
        select="$Order/Total"/>
    </OrderTotal>
  </pd:inputBindings>
</pd:activity>
Apache CamelJava DSL, generated
// the whole activity, as emitted
.setProperty("CustomerId",
    simple("${exchangeProperty.Order}"))
.setProperty("OrderTotal",
    simple("${exchangeProperty.Order}"))
.log(LoggingLevel.TRACE,
    "mapper Build Order Summary (inline)")

Where the semantics diverge

Only one shape qualifies for inline translation, and it is narrower than it looks. A Mapper activity is only translated field-by-field when every one of its input bindings is a bare <xsl:value-of select="$Var/path"/>, there are six bindings or fewer, and none of them is a literal, a function call, a concatenation or an XPath predicate. One binding outside that shape, or a seventh binding of any shape, and the entire activity falls back to a single bean call instead, described below.

Even inside that narrow shape, the source path after the variable is checked but not kept. The rule validates that path has no :, [ or ( in its first segment, then discards it: the emitted expression is ${exchangeProperty.<Var>}, the variable name alone. The code sample above is real: $Order/CustomerId and $Order/Total are two different fields on the same source object, and both compile to the identical expression. If Order is a property holding a single scalar this is harmless, because there is only one thing it could mean; if Order is a structured object, every binding that reads from it collapses onto the whole object, and whichever field the route reads next determines whether that accidentally still works.

Everything else becomes .bean("<name>Mapper", "map"), and the rule does not write that bean. No tib: function handling, no XSLT translation, no partial mapping of the bindings that were simple: the whole activity becomes one call to a bean whose implementation is presumed to exist. When nothing defines a Spring bean under that name, the generator’s project-wide auto-stub pass notices the unresolved reference and writes a pass-through stand-in into a shared CommonStubBeans configuration: body unchanged, one debug log line, guarded by @ConditionalOnMissingBean so a real @Component registered under the same name quietly takes over. The route compiles and starts. The mapping does nothing until that bean is written.

Neither outcome is marked. The rule is unconditional and attaches no TODO_HUMAN comment in either branch, which is also why the coverage report carries this type as translated: correct by the report’s own definition, an unconditional rule with no marker, but that definition does not distinguish a one-property copy that happens to be right from a silent no-op stub that happens to compile.

What the toolchain does

Reads the activity’s pd:inputBindings. If there are six or fewer and every one matches <xsl:value-of select="$Var/path"/> with a plain, unprefixed path, it emits one setProperty per binding, target the sanitised output field name, value ${exchangeProperty.<Var>}, followed by a single trace-level log line. Otherwise it emits one .bean("<activityName>Mapper", "map") call and leaves the implementation to whatever bean is registered under that name at runtime, auto-stubbed to a pass-through if nothing else claims it.