enhancement
major
minor
major
minor
major
#29880
XIO: Import of an evolving external format: report unknown elements, reject a second composite container with a location, match several values in one <switch> case
The XML import (tl-xio) of an external format that evolves over time (found in E-Home, haumacher/ehome #32: the ETS import was written for KNX project schema 11, an ETS 6 file uses schema 23) hides three kinds of problems. This ticket consolidates #29880, #29881 and #29882.
Unknown elements are skipped silently
DispatchingImporter (<dispatch>) uses SkipDeep as its default handler: an element without a configured handler is skipped together with its whole subtree, and nothing is reported. New elements of a later schema version (e.g. ModuleDefs, Format/Enumeration, Locations/Space, LdCtrlMasterReset) simply vanish from the import; some were found only by comparing element paths of the files by hand.
A second composite container aborts the whole import
If an import definition links an object that already has a composite container into a second composite reference, the persistence layer throws IllegalStateException: Object '…' is part of multiple containers: [...]. The exception aborts the entire import (the transaction, then the whole command); the cause surfaces only later, as a failing script evaluation (Evaluation of 'container($x)' failed … DeletedObject …), and does not point to the place in the document. In the KNX schema-23 format one ParameterRefRef is placed in several choose/when branches; the ETS import mapped it to a composition, and an ETS 6 file could not be imported at all.
A <switch> case matches a single value only
PropertySwitch maps exactly one attribute value to each case. Two values that mean the same thing (ETS 6 writes boolean flags as true/`false`, ETS 4 wrote 1`/`0) need two cases with identical handler configurations.
Lösung
Unknown elements. <dispatch> gets the option unknown="skip|warn|error". It applies to an element that has neither a <tag> entry nor a configured <default>: skip (the default) skips the subtree silently, warn reports the tag name and its location as a warning, error as an error; both then skip the subtree. The setting is inherited at runtime through the ImportContext: a <dispatch> with an explicit setting establishes it for its whole subtree, a <dispatch> without one uses the inherited setting. So <handler unknown="warn"> on the root covers a whole import definition, including the implicit empty dispatches of leaf elements.
Second composite container. Before a composite reference is set or added to, the model binding (AbstractModelBinding, shared by the application and the transient binding) compares the current container and container reference of the value with the target. On a mismatch, an error naming the object, its existing container and reference and the new ones is reported with the location in the document, the link is skipped and the import continues; the object stays in its first container. DefaultImportContext reports the message key of a TopLogicException thrown by the binding directly instead of wrapping it into the generic "setting property failed" message.
Framework fix on the way: TransientTLObjectImpl.tContainer() / tContainerReference() knew only the creation context and ignored composite links made afterwards. They now derive the container from the referer through a composite reference when no creation context was given; tValid() follows that derived container.
Multi-value case. The value of a <case> in a <switch> is a comma-separated list of values (<case value="1, true">), each of which selects the case. The entries are trimmed and empty entries are kept: value="" or a trailing comma (<case value="0, false,">) stands for the empty attribute value. A value listed in two cases of the same switch is a configuration error reported when the import definition is loaded. Single-value cases are unchanged.
Test
test.com.top_logic.xio.importer.TestXmlImporter: an import definition with unknown="warn" and a document with an unknown element (the import completes, one warning with tag name, line and column); a composite reference and a document that puts the same object under two container elements (one error with the location of the second occurrence, the object stays in its first container); a switch whose case lists two values (both select the same handler), a case with an empty value. test.com.top_logic.model.impl.TestTransientObjectValidity: container derived from a composite link.