Class DexpiXmlWriter
ProcessSystems created from DEXPI data back into a lightweight
DEXPI XML representation.
The writer groups all discovered DexpiStream segments by line number (or fluid code when
a line is not available) to generate simple <PipingNetworkSystem> elements with
associated <PipingNetworkSegment> children.
- Version:
- 1.0
- Author:
- NeqSim
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static classSimple connection descriptor linking an outlet nozzle to an inlet nozzle. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final ThreadLocal<DecimalFormat> private static final Pattern -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate static voidappendConnectionSystem(Document document, Element parent, List<DexpiXmlWriter.NozzleConnection> connections, Set<String> usedIds, Map<String, Element> valvePipingComponents, Map<String, double[]> nozzlePositions) Appends a PipingNetworkSystem containing Connection elements for equipment wiring.private static voidappendEquipmentBarFromSimulation(Document document, Element element, ProcessEquipmentInterface unit, DexpiLayoutEngine.EquipmentPosition position, String labelId, String equipmentId) Appends an EquipmentBarLabel using simulation results from the equipment outlet.private static voidappendGenericAttribute(Document document, Element parent, String name, String value) private static voidprivate static voidappendIEC81346Attributes(Document document, Element genericAttributes, ProcessEquipmentInterface unit) Appends IEC 81346 reference designation attributes to the generic attributes element.private static voidappendInstrumentLabelText(Document document, Element label, String text, double x, double y, String pifId, String[] dependantAttributes) Appends a Text element inside an instrument label.private static voidappendInstrumentPosition(Document document, Element parent, double x, double y) Appends a Position element with Location, Axis, and Reference for an instrument bubble.private static voidappendInstruments(Document document, Element parent, Map<String, MeasurementDeviceInterface> transmitters, Map<String, ControllerDeviceInterface> controllers, Set<String> usedIds, Map<String, DexpiLayoutEngine.EquipmentPosition> layoutPositions, Map<String, double[]> nozzlePositions, ProcessSystem processSystem) Appends DEXPI instrumentation elements for transmitters and controllers.private static voidappendMechanicalDesignAttributes(Document document, Element parent, ProcessEquipmentInterface unit) Appends a GenericAttributes set with mechanical design parameters for the equipment.private static voidappendNativeEquipment(Document document, Element parent, ProcessEquipmentInterface unit, Set<String> usedIds, String inletNozzleId, List<String> outletNozzleIds, DexpiLayoutEngine.EquipmentPosition position, int labelIndex, Map<String, double[]> nozzlePositions) Appends a native NeqSim equipment (non-DEXPI-origin) to the document using reverse mapping.private static voidappendNozzle(Document document, Element parent, String nozzleId, Set<String> usedIds, Map<String, double[]> nozzlePositions) Appends a Nozzle child element to the parent equipment element with optional position.private static voidappendNumericAttribute(Document document, Element parent, String name, double value, String unit) private static voidappendPipingNetworkSegment(Document document, Element parent, DexpiStream stream, Set<String> usedIds) private static voidappendPipingNetworkSystem(Document document, Element parent, String key, List<DexpiStream> streams, Set<String> usedIds) private static voidappendProcessUnit(Document document, Element parent, DexpiProcessUnit processUnit, Set<String> usedIds, String inletNozzleId, List<String> outletNozzleIds, DexpiLayoutEngine.EquipmentPosition position, int labelIndex, Map<String, double[]> nozzlePositions) private static voidappendSignalNode(Document document, Element parent, String nodeId, double x, double y) Appends a signal Node with position inside a ConnectionPoints element.private static voidappendSimulationResults(Document document, Element genericAttributes, ProcessEquipmentInterface unit) Appends simulation result attributes (P, T, flow) from equipment outlet streams.private static voidbuildConnections(ProcessSystem processSystem, Map<Integer, String> outletStreamToNozzle, Map<String, String> inletNozzles, List<DexpiXmlWriter.NozzleConnection> connections) Builds connections between equipment by matching inlet stream identity to outlet stream nozzles.private static DexpiLayoutEngine.StreamTableEntrybuildStreamEntry(DecimalFormat df, String streamLabel, StreamInterface stream) Builds a single stream table entry from a stream's simulation results.private static ElementbuildValvePipingComponent(Document document, ProcessEquipmentInterface unit, Set<String> usedIds, String inletNozzleId, List<String> outletNozzleIds, DexpiLayoutEngine.EquipmentPosition position, int labelIndex, Map<String, double[]> nozzlePositions) Builds a PipingComponent XML element for a valve unit.Collects mechanical design parameters from equipment for display in the bar label.private static List<DexpiLayoutEngine.StreamTableEntry> collectStreamTableData(ProcessSystem processSystem) Collects stream data for the stream table from process system equipment.private static Documentprivate static ElementcreatePlantInformation(Document document) private static StringdefaultComponentClass(EquipmentEnum mapped, String elementName) private static StringderiveControllerTag(String transmitterTag) Derives the controller tag from a transmitter tag.private static StringDetects valve fail position from the tag name convention per NORSOK Z-003.private static StringDetects equipment orientation from the type.private static booleandetectSafetySystem(String tag) Detects whether an instrument tag indicates a Safety Instrumented System (SIS) device rather than a DCS device.private static StringfindParentEquipment(MeasurementDeviceInterface device, ProcessSystem processSystem) Finds the name of the equipment whose inlet or outlet stream matches the transmitter's stream.private static StringfirstNonBlank(String... values) private static StringformatMechValue(double value) Formats a mechanical design value for display.private static StreamInterfaceGets the outlet stream of a process equipment for simulation result extraction.private static booleanprivate static booleanReturnstrueif the unit represents a DEXPI piping component (valve) rather than an Equipment element.private static StringmapComponentClassUri(String componentClass) Maps a DEXPI ComponentClass name to its RDL URI.private static String[]parseIsaTag(String tag) Parses an ISA-style tag (e.g.private static voidregisterNozzlePositions(DexpiLayoutEngine.EquipmentPosition position, String inNozzle, List<String> outNozzles, Map<String, double[]> nozzlePositions) Registers nozzle positions for connection line geometry.private static voidregisterOutletNozzles(ProcessEquipmentInterface unit, List<String> outNozzles, Map<Integer, String> outletStreamToNozzle) Registers outlet stream identity hashes to their nozzle IDs.private static voidregisterPassThroughStreams(ProcessSystem processSystem, Map<Integer, String> outletStreamToNozzle) Registers pass-through Streams in the outlet-stream-to-nozzle map.private static StringReturns the DEXPI ComponentClass string for a native NeqSim equipment type.private static StringDetermines the DEXPI valve ComponentClass from the tag name.static voidPerforms a bi-directional DEXPI round-trip: reads an existing DEXPI XML P&ID, creates a NeqSim process model from it using the provided fluid template, runs the simulation, and writes the enriched results back to DEXPI XML.private static StringsanitizeIdentifier(String name) private static StringstripHyphens(String value) private static StringuniqueIdentifier(String prefix, String name, Set<String> usedIds) static voidwrite(ProcessSystem processSystem, File file) Writes the providedProcessSystemto a DEXPI XML file.static voidwrite(ProcessSystem processSystem, File file, Map<String, MeasurementDeviceInterface> transmitters, Map<String, ControllerDeviceInterface> controllers) Writes the providedProcessSystemto a DEXPI XML file, including instrument and controller data when provided.static voidwrite(ProcessSystem processSystem, OutputStream outputStream) Writes the providedProcessSystemto a DEXPI XML stream.static voidwrite(ProcessSystem processSystem, OutputStream outputStream, Map<String, MeasurementDeviceInterface> transmitters, Map<String, ControllerDeviceInterface> controllers) Writes the providedProcessSystemto a DEXPI XML stream, including instrument and controller data when provided.private static voidwriteDocument(Document document, OutputStream outputStream)
-
Field Details
-
NON_IDENTIFIER
-
DECIMAL_FORMAT
-
-
Constructor Details
-
DexpiXmlWriter
private DexpiXmlWriter()
-
-
Method Details
-
roundTrip
public static void roundTrip(File inputFile, File outputFile, Stream templateStream) throws IOException, DexpiXmlReaderException Performs a bi-directional DEXPI round-trip: reads an existing DEXPI XML P&ID, creates a NeqSim process model from it using the provided fluid template, runs the simulation, and writes the enriched results back to DEXPI XML.This enables a "digital twin" workflow where P&ID designs are imported, simulated with rigorous thermodynamics, and exported back with updated process data (temperatures, pressures, flow rates, compositions).
- Parameters:
inputFile- the source DEXPI XML file to readoutputFile- the destination file for the enriched DEXPI XMLtemplateStream- the template stream providing fluid composition for simulation- Throws:
IOException- if reading or writing failsDexpiXmlReaderException- if the DEXPI XML cannot be parsed
-
write
Writes the providedProcessSystemto a DEXPI XML file.- Parameters:
processSystem- process model to exportfile- output file- Throws:
IOException- if writing fails
-
write
public static void write(ProcessSystem processSystem, File file, Map<String, MeasurementDeviceInterface> transmitters, Map<String, ControllerDeviceInterface> controllers) throws IOException Writes the providedProcessSystemto a DEXPI XML file, including instrument and controller data when provided.- Parameters:
processSystem- process model to exportfile- output filetransmitters- map of tag name to transmitter (may be null)controllers- map of tag name to controller (may be null)- Throws:
IOException- if writing fails
-
write
Writes the providedProcessSystemto a DEXPI XML stream.- Parameters:
processSystem- process model to exportoutputStream- destination stream- Throws:
IOException- if writing fails
-
write
public static void write(ProcessSystem processSystem, OutputStream outputStream, Map<String, MeasurementDeviceInterface> transmitters, Map<String, ControllerDeviceInterface> controllers) throws IOException Writes the providedProcessSystemto a DEXPI XML stream, including instrument and controller data when provided.- Parameters:
processSystem- process model to exportoutputStream- destination streamtransmitters- map of tag name to transmitter (may be null)controllers- map of tag name to controller (may be null)- Throws:
IOException- if writing fails
-
createDocument
- Throws:
IOException
-
createPlantInformation
-
appendProcessUnit
-
appendNativeEquipment
private static void appendNativeEquipment(Document document, Element parent, ProcessEquipmentInterface unit, Set<String> usedIds, String inletNozzleId, List<String> outletNozzleIds, DexpiLayoutEngine.EquipmentPosition position, int labelIndex, Map<String, double[]> nozzlePositions) Appends a native NeqSim equipment (non-DEXPI-origin) to the document using reverse mapping.- Parameters:
document- the XML documentparent- the parent elementunit- the process equipmentusedIds- set of used IDsinletNozzleId- the inlet nozzle ID to createoutletNozzleIds- the outlet nozzle IDs to createposition- the computed layout position (may be null)labelIndex- label counter for unique IDsnozzlePositions- map of nozzle positions for graphical rendering
-
appendNozzle
private static void appendNozzle(Document document, Element parent, String nozzleId, Set<String> usedIds, Map<String, double[]> nozzlePositions) Appends a Nozzle child element to the parent equipment element with optional position.- Parameters:
document- the XML documentparent- the equipment elementnozzleId- the nozzle IDusedIds- set of used IDsnozzlePositions- map of nozzle positions (may be null)
-
appendSimulationResults
private static void appendSimulationResults(Document document, Element genericAttributes, ProcessEquipmentInterface unit) Appends simulation result attributes (P, T, flow) from equipment outlet streams.- Parameters:
document- the XML documentgenericAttributes- the GenericAttributes element to append tounit- the process equipment
-
appendMechanicalDesignAttributes
private static void appendMechanicalDesignAttributes(Document document, Element parent, ProcessEquipmentInterface unit) Appends a GenericAttributes set with mechanical design parameters for the equipment. Only attributes with non-zero/non-default values are exported.- Parameters:
document- the XML documentparent- the equipment elementunit- the process equipment
-
appendEquipmentBarFromSimulation
private static void appendEquipmentBarFromSimulation(Document document, Element element, ProcessEquipmentInterface unit, DexpiLayoutEngine.EquipmentPosition position, String labelId, String equipmentId) Appends an EquipmentBarLabel using simulation results from the equipment outlet.- Parameters:
document- the XML documentelement- the equipment elementunit- the process equipmentposition- the equipment positionlabelId- the unique label IDequipmentId- the equipment element ID
-
collectMechanicalDesignRows
Collects mechanical design parameters from equipment for display in the bar label. Returns rows only for parameters that have been set (non-zero, non-default).- Parameters:
unit- the process equipment- Returns:
- list of label-value pairs (may be empty)
-
formatMechValue
Formats a mechanical design value for display.- Parameters:
value- the value to format- Returns:
- formatted string
-
getEquipmentOutlet
Gets the outlet stream of a process equipment for simulation result extraction.- Parameters:
unit- the process equipment- Returns:
- the outlet stream, or null if not available
-
reverseMapComponentClass
Returns the DEXPI ComponentClass string for a native NeqSim equipment type.- Parameters:
unit- the process equipment- Returns:
- the DEXPI ComponentClass name
-
isValveType
Returnstrueif the unit represents a DEXPI piping component (valve) rather than an Equipment element. In the DEXPI schema, valves are PipingComponent elements and should be embedded inside PipingNetworkSegment elements rather than exported as top-level Equipment.- Parameters:
unit- the process equipment to check- Returns:
- true if the unit should be rendered as a PipingComponent
-
buildValvePipingComponent
private static Element buildValvePipingComponent(Document document, ProcessEquipmentInterface unit, Set<String> usedIds, String inletNozzleId, List<String> outletNozzleIds, DexpiLayoutEngine.EquipmentPosition position, int labelIndex, Map<String, double[]> nozzlePositions) Builds a PipingComponent XML element for a valve unit.- Parameters:
document- the XML documentunit- the valve unitusedIds- set of used IDsinletNozzleId- the inlet nozzle IDoutletNozzleIds- the outlet nozzle IDsposition- the computed layout position (may be null)labelIndex- label counter for unique IDsnozzlePositions- map of nozzle positions for graphical rendering- Returns:
- the PipingComponent element
-
registerOutletNozzles
private static void registerOutletNozzles(ProcessEquipmentInterface unit, List<String> outNozzles, Map<Integer, String> outletStreamToNozzle) Registers outlet stream identity hashes to their nozzle IDs.For single-outlet equipment, the first (and only) nozzle maps to the gas/primary outlet. For separators, the first nozzle maps to the gas outlet, the second to the liquid outlet, and for three-phase separators, the third maps to the water outlet.
- Parameters:
unit- the process equipmentoutNozzles- the list of outlet nozzle IDsoutletStreamToNozzle- map to populate with identity hash to nozzle ID
-
registerNozzlePositions
private static void registerNozzlePositions(DexpiLayoutEngine.EquipmentPosition position, String inNozzle, List<String> outNozzles, Map<String, double[]> nozzlePositions) Registers nozzle positions for connection line geometry.Inlet nozzles are placed at the left edge of the equipment shape (x - 10), and outlet nozzles at the right edge (x + 10). Multiple outlets are vertically offset to match the layout.
- Parameters:
position- the equipment position (may be null)inNozzle- the inlet nozzle IDoutNozzles- the outlet nozzle IDsnozzlePositions- map to populate with nozzle ID to {x, y} coordinates
-
registerPassThroughStreams
private static void registerPassThroughStreams(ProcessSystem processSystem, Map<Integer, String> outletStreamToNozzle) Registers pass-through Streams in the outlet-stream-to-nozzle map.When a user creates
new Stream("gas-out", separator.getGasOutStream()), the wrapping Stream delegatesgetFluid()to the source. This method detects such wrappers by matching fluid identity and registers the wrapper itself so downstream equipment that took the wrapper as its inlet can be connected.- Parameters:
processSystem- the process systemoutletStreamToNozzle- map of outlet stream identity hash to nozzle ID
-
buildConnections
private static void buildConnections(ProcessSystem processSystem, Map<Integer, String> outletStreamToNozzle, Map<String, String> inletNozzles, List<DexpiXmlWriter.NozzleConnection> connections) Builds connections between equipment by matching inlet stream identity to outlet stream nozzles.For each equipment that extends
TwoPortEquipment, the inlet stream is looked up in the outlet-stream-to-nozzle map to find the upstream nozzle. This correctly resolves branching (e.g. separator gas and liquid outlets going to different downstream equipment).- Parameters:
processSystem- the process systemoutletStreamToNozzle- map of outlet stream identity hash to nozzle IDinletNozzles- map of equipment name to inlet nozzle IDconnections- list to populate with connections
-
appendConnectionSystem
private static void appendConnectionSystem(Document document, Element parent, List<DexpiXmlWriter.NozzleConnection> connections, Set<String> usedIds, Map<String, Element> valvePipingComponents, Map<String, double[]> nozzlePositions) Appends a PipingNetworkSystem containing Connection elements for equipment wiring.- Parameters:
document- the XML documentparent- the root elementconnections- the list of connectionsusedIds- set of used IDsvalvePipingComponents- pre-built PipingComponent elements for valves, keyed by inlet nozzle IDnozzlePositions- map of nozzle ID to {x, y} coordinates for line geometry
-
appendPipingNetworkSystem
-
appendPipingNetworkSegment
private static void appendPipingNetworkSegment(Document document, Element parent, DexpiStream stream, Set<String> usedIds) -
appendGenericAttribute
-
appendGenericAttribute
-
appendNumericAttribute
-
appendInstruments
private static void appendInstruments(Document document, Element parent, Map<String, MeasurementDeviceInterface> transmitters, Map<String, ControllerDeviceInterface> controllers, Set<String> usedIds, Map<String, DexpiLayoutEngine.EquipmentPosition> layoutPositions, Map<String, double[]> nozzlePositions, ProcessSystem processSystem) Appends DEXPI instrumentation elements for transmitters and controllers.Each transmitter becomes a
ProcessInstrumentationFunctionwith aProcessSignalGeneratingFunctionchild. Controllers that share a loop tag with a transmitter are linked viaSignalConveyingFunctionandActuatingFunction. Finally, anInstrumentationLoopFunctiongroups each loop's elements.- Parameters:
document- the XML documentparent- the root element to append totransmitters- map of tag to transmittercontrollers- map of tag to controller (may be null)usedIds- set of already used XML IDslayoutPositions- equipment layout positions keyed by equipment namenozzlePositions- nozzle positions keyed by nozzle IDprocessSystem- the process system for stream-to-equipment matching
-
findParentEquipment
private static String findParentEquipment(MeasurementDeviceInterface device, ProcessSystem processSystem) Finds the name of the equipment whose inlet or outlet stream matches the transmitter's stream.- Parameters:
device- the measurement deviceprocessSystem- the process system- Returns:
- the equipment name, or null if not found
-
appendInstrumentPosition
Appends a Position element with Location, Axis, and Reference for an instrument bubble.- Parameters:
document- the XML documentparent- the element to append tox- the X coordinatey- the Y coordinate
-
appendInstrumentLabelText
private static void appendInstrumentLabelText(Document document, Element label, String text, double x, double y, String pifId, String[] dependantAttributes) Appends a Text element inside an instrument label.- Parameters:
document- the XML documentlabel- the Label elementtext- the display textx- X position of the texty- Y position of the textpifId- the parent ProcessInstrumentationFunction IDdependantAttributes- the DependantAttribute names for TextStringFormatSpecification
-
appendSignalNode
private static void appendSignalNode(Document document, Element parent, String nodeId, double x, double y) Appends a signal Node with position inside a ConnectionPoints element.- Parameters:
document- the XML documentparent- the ConnectionPoints elementnodeId- the unique node IDx- the X coordinatey- the Y coordinate
-
parseIsaTag
-
deriveControllerTag
Derives the controller tag from a transmitter tag. For example, "PT-HP sep" becomes "PC-HP sep", "LT-HP sep" becomes "LC-HP sep".- Parameters:
transmitterTag- the transmitter tag- Returns:
- the expected controller tag, or null if not derivable
-
collectStreamTableData
private static List<DexpiLayoutEngine.StreamTableEntry> collectStreamTableData(ProcessSystem processSystem) Collects stream data for the stream table from process system equipment.Iterates through all equipment in the process system, extracting temperature, pressure, flow rate, and phase information from each outlet stream.
- Parameters:
processSystem- the process system to extract stream data from- Returns:
- list of stream table entries for rendering
-
buildStreamEntry
private static DexpiLayoutEngine.StreamTableEntry buildStreamEntry(DecimalFormat df, String streamLabel, StreamInterface stream) Builds a single stream table entry from a stream's simulation results.- Parameters:
df- the decimal format for numeric valuesstreamLabel- the stream label/numberstream- the stream to extract data from- Returns:
- the stream table entry, or null if data is unavailable
-
defaultComponentClass
-
uniqueIdentifier
-
sanitizeIdentifier
-
appendIEC81346Attributes
private static void appendIEC81346Attributes(Document document, Element genericAttributes, ProcessEquipmentInterface unit) Appends IEC 81346 reference designation attributes to the generic attributes element.If the equipment has an IEC 81346 reference designation set (via
ReferenceDesignationGenerator), the following attributes are added:IEC81346ReferenceDesignation: The full reference designation stringIEC81346FunctionDesignation: The function aspectIEC81346ProductDesignation: The product aspectIEC81346LocationDesignation: The location aspectIEC81346LetterCode: The equipment letter code (e.g. "B", "K", "Q")
- Parameters:
document- the XML documentgenericAttributes- the parent element for generic attributesunit- the process equipment
-
stripHyphens
-
firstNonBlank
-
isBlank
-
detectOrientation
Detects equipment orientation from the type. Per ISO 10628, separators are typically marked vertical (V) while rotating and heat-transfer equipment are horizontal (H).- Parameters:
unit- the process equipment- Returns:
- "V" for vertical, "H" for horizontal, or null if not applicable
-
detectFailPosition
Detects valve fail position from the tag name convention per NORSOK Z-003.Tags starting with "XV", "ESD", or "HIPPS" are assumed fail-closed (FC). Tags starting with "HV" are assumed fail-open (FO). Other valves return null (no automatic fail position).
- Parameters:
unit- the valve equipment- Returns:
- fail position code (FC, FO), or null
-
reverseMapValveClass
Determines the DEXPI valve ComponentClass from the tag name. Different valve prefixes indicate different valve types per ISA/NORSOK conventions.- Parameters:
unit- the valve equipment- Returns:
- the DEXPI ComponentClass (GlobeValve, GateValve, BallValve, CheckValve, ButterflyValve)
-
detectSafetySystem
Detects whether an instrument tag indicates a Safety Instrumented System (SIS) device rather than a DCS device. Safety tags typically have key letters like XV (shutdown), SD (shutdown), ZS (limit switch on safety valve), or SV (safety valve).- Parameters:
tag- the ISA instrument tag- Returns:
- true if the tag indicates a safety-instrumented function
-
mapComponentClassUri
-
writeDocument
- Throws:
IOException
-