feat(fls): write the topology of a .fls, loaded by Java as the original
topologyWriter.ts writes konfiguration.xml from Java's view of a project: the version line, the node items (label position, device with name, host label flags, interfaces or ports), the cable items and the documentation items. What a device's constructor makes is changed through getters, as XMLEncoder does, and more is added; fewer than it makes set the list anew. Cable ends name the port objects the getters return (the writer now names a getter's result, <void id="Port0" property="port"/>), and each cable carries the nodes the editor draws it between. Checked by Java against Java: every corpus file, read and written again, loads in Java FILIUS (the oracle's loading method, --sha256 ties its result to the written bytes) to the same devices, names, positions, interfaces, cables and documentation as the original; so does a synthetic topology with what the corpus never sets. The oracle and the reader now also report a cable's drawing ends (JCablePanel ziel1/ziel2): in the corpus the nodes it joins, for all 183 cables. Mutation probes rewrite the files and let Java load each mutant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -60,6 +60,11 @@ export interface FlsPortReference {
|
||||
export interface FlsLink {
|
||||
ends: [FlsPortReference, FlsPortReference];
|
||||
wireless: boolean;
|
||||
/**
|
||||
* The nodes the editor draws the cable between (JCablePanel ziel1, ziel2),
|
||||
* by index; null where the file names none.
|
||||
*/
|
||||
panel: [number | null, number | null];
|
||||
}
|
||||
|
||||
export type FlsColor = [red: number, green: number, blue: number, alpha: number];
|
||||
@@ -146,7 +151,10 @@ export function readTopology(values: readonly JavaValue[]): FlsTopology {
|
||||
const nodes: FlsNode[] = [];
|
||||
for (const [index, item] of nodeItems.entries()) {
|
||||
const node = context.node(item, index, nodes.length);
|
||||
if (node !== undefined) nodes.push(node);
|
||||
if (node !== undefined) {
|
||||
if (isJavaObject(item)) context.nodeItems.set(item, nodes.length);
|
||||
nodes.push(node);
|
||||
}
|
||||
}
|
||||
const links: FlsLink[] = [];
|
||||
for (const [index, item] of cableItems.entries()) {
|
||||
@@ -168,6 +176,8 @@ function listOf(value: JavaValue | undefined, className: string): JavaValue[] {
|
||||
class Reader {
|
||||
/** Every port object a node owns, to resolve cable ends by identity as Java does. */
|
||||
private readonly portOwners = new Map<JavaObject, FlsPortReference>();
|
||||
/** Every node item read, to resolve a cable panel's ends. */
|
||||
readonly nodeItems = new Map<JavaObject, number>();
|
||||
|
||||
constructor(private readonly warnings: string[]) {}
|
||||
|
||||
@@ -310,9 +320,15 @@ class Reader {
|
||||
this.warnings.push(`cable ${itemIndex + 1}: an end is not a port of a device, left out`);
|
||||
return undefined;
|
||||
}
|
||||
const panel = (item as JavaObject).properties.get('kabelpanel');
|
||||
const panelEnd = (property: string) => {
|
||||
const target = isJavaObject(panel) ? panel.properties.get(property) : undefined;
|
||||
return isJavaObject(target) ? (this.nodeItems.get(target) ?? null) : null;
|
||||
};
|
||||
return {
|
||||
ends: [first, second],
|
||||
wireless: this.booleanProperty(cable, 'wireless', `cable ${itemIndex + 1}`),
|
||||
panel: [panelEnd('ziel1'), panelEnd('ziel2')],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user