Skip to content

Commit ff83f0f

Browse files
committed
save file update
1 parent b842ee2 commit ff83f0f

2 files changed

Lines changed: 88 additions & 87 deletions

File tree

src/neqsim/__init__.py

Lines changed: 81 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -31,115 +31,109 @@ def setDatabase(connectionString):
3131
jneqsim.util.database.NeqSimDataBase.setCreateTemporaryTables(True)
3232

3333

34-
def save_neqsim(javaobject, filename):
35-
"""
36-
Serialize a Java object (such as a NEQSim ProcessSystem) to XML
37-
using XStream, then compress and save it as a .gz file.
38-
39-
Args:
40-
javaobject: A Java object that XStream can serialize (e.g., neqsim.process.processmodel.ProcessSystem).
41-
filename (str): The path (including filename) to write the compressed XML file.
42-
For clarity, you can use a .xml.gz extension, for example "myProcess.xml.gz".
43-
44-
Returns:
45-
bool: True if the file is successfully written.
46-
47-
Raises:
48-
Any exception raised by XStream serialization, file I/O, or gzip operations
49-
will propagate unless caught by the caller.
50-
51-
Usage Example:
52-
# 1. Ensure JPype has started the JVM and XStream is on the classpath:
53-
# if not jpype.isJVMStarted():
54-
# jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", f"-Djava.class.path=path/to/xstream.jar")
55-
56-
# 2. Acquire or build the NEQSim process object (javaobject).
57-
# process = ... # your neqsim.process.processmodel.ProcessSystem
58-
59-
# 3. Call save_neqsim:
60-
# save_neqsim(process, "myProcess.xml.gz")
61-
"""
62-
# Instantiate XStream from the Java packages
63-
xstream = jpype.JPackage("com.thoughtworks.xstream").XStream()
64-
65-
# Convert the Java object to an XML string (java.lang.String)
66-
xml_java_string = xstream.toXML(javaobject)
67-
68-
# Convert java.lang.String to a native Python string
69-
xml_python_string = str(xml_java_string)
70-
71-
# Compress and save the string as UTF-8 bytes in a .gz file
72-
with gzip.open(filename, "wb") as f:
73-
f.write(xml_python_string.encode("utf-8"))
74-
75-
return True
76-
77-
7834
def open_neqsim(filename, allow_all=True, wildcard_permission=None):
7935
"""
80-
Decompress and deserialize a Java object (e.g., a NEQSim ProcessSystem)
81-
from a gzipped XStream XML file.
36+
Open and deserialize a NEQSim Java object from either a .gz or .zip XStream-serialized XML file.
8237
83-
Args:
84-
filename (str): Path to the gzipped file (e.g. 'process.neqsim').
85-
allow_all (bool): If True, uses AnyTypePermission to allow all classes
86-
during deserialization. This is simple but not recommended for
87-
production security.
88-
wildcard_permission (list of str, optional):
89-
A list of wildcard patterns for XStream to allow. For example,
90-
['neqsim.**'] would allow classes under 'neqsim'.
38+
Supports:
39+
- GZipped XML: .xml.gz
40+
- Zipped XML: .zip (must contain a file named 'process.xml')
9141
9242
Returns:
93-
object: The deserialized Java object (e.g., a NEQSim ProcessSystem),
94-
or None if an error occurs.
95-
96-
Raises:
97-
Any exceptions raised by file I/O, gzip, XStream, or JPype will
98-
propagate unless caught by the caller.
99-
100-
Usage Example:
101-
# Ensure the JVM is started and the XStream JAR is on the classpath.
102-
# jpype.startJVM(..., classpath=[...])
103-
104-
# open_neqsim("myProcess.neqsim", allow_all=True)
43+
object: The deserialized Java object.
10544
"""
106-
# 1. Create an XStream instance
107-
xstream_cls = jpype.JPackage("com.thoughtworks.xstream").XStream
108-
xstream = xstream_cls()
45+
import os
46+
47+
# Instantiate XStream
48+
XStream = jpype.JClass("com.thoughtworks.xstream.XStream")
49+
xstream = XStream()
10950

110-
# 2. Configure security permissions
51+
# Configure security
11152
security_pkg = jpype.JPackage("com.thoughtworks.xstream.security")
11253
if allow_all:
113-
# Allow everything (not recommended in production)
114-
anyTypePermission_cls = security_pkg.AnyTypePermission
115-
xstream.addPermission(anyTypePermission_cls.ANY)
54+
xstream.addPermission(security_pkg.AnyTypePermission.ANY)
11655
elif wildcard_permission is not None:
117-
# e.g. wildcard_permission = ["neqsim.**"]
118-
wildcard_cls = security_pkg.WildcardTypePermission
119-
xstream.addPermission(wildcard_cls(wildcard_permission))
120-
else:
121-
# By default, XStream might reject many classes.
122-
# The user can add more specific permissions here.
123-
pass
124-
125-
# 3. Read and decompress the file
56+
xstream.addPermission(security_pkg.WildcardTypePermission(wildcard_permission))
57+
58+
# Detect file format by extension
59+
ext = os.path.splitext(filename)[-1].lower()
60+
12661
try:
127-
with gzip.open(filename, "rb") as f:
128-
xml_bytes = f.read()
129-
xml_str = xml_bytes.decode("utf-8")
62+
if ext == ".gz":
63+
with gzip.open(filename, "rb") as f:
64+
xml_bytes = f.read()
65+
elif ext == ".zip":
66+
import zipfile
67+
with zipfile.ZipFile(filename, 'r') as zf:
68+
with zf.open('process.xml') as f:
69+
xml_bytes = f.read()
70+
else:
71+
raise ValueError(f"Unsupported file extension: {ext}")
13072
except Exception as e:
131-
print(f"[open_neqsim] Failed to read/decompress file: {e}")
73+
print(f"[open_neqsim] Failed to read/compress/decompress file: {e}")
13274
return None
13375

134-
# 4. Deserialize using XStream
76+
# Deserialize
13577
try:
78+
xml_str = xml_bytes.decode("utf-8")
13679
java_object = xstream.fromXML(xml_str)
13780
return java_object
13881
except Exception as e:
13982
print(f"[open_neqsim] Failed to deserialize object: {e}")
14083
return None
14184

14285

86+
def save_neqsim(javaobject, filename):
87+
"""
88+
Serialize a Java object (e.g., NEQSim ProcessSystem) to XML using XStream,
89+
and save it as a compressed ZIP file containing one XML file.
90+
91+
Args:
92+
javaobject: A Java object that XStream can serialize.
93+
filename (str): The path to the ZIP file to write (e.g., "myProcess.zip").
94+
95+
Returns:
96+
bool: True if the file is successfully written, False otherwise.
97+
"""
98+
if not jpype.isJVMStarted():
99+
raise RuntimeError("JVM is not started. Please start the JVM with the correct classpath.")
100+
101+
try:
102+
# Java imports
103+
XStream = jpype.JClass("com.thoughtworks.xstream.XStream")
104+
FileOutputStream = jpype.JClass("java.io.FileOutputStream")
105+
BufferedOutputStream = jpype.JClass("java.io.BufferedOutputStream")
106+
ZipOutputStream = jpype.JClass("java.util.zip.ZipOutputStream")
107+
ZipEntry = jpype.JClass("java.util.zip.ZipEntry")
108+
OutputStreamWriter = jpype.JClass("java.io.OutputStreamWriter")
109+
File = jpype.JClass("java.io.File")
110+
111+
# Create XStream instance and configure security
112+
xstream = XStream()
113+
xstream.allowTypesByWildcard(["neqsim.**"])
114+
115+
# Setup output stream and ZIP structure
116+
file = File(filename)
117+
fout = BufferedOutputStream(FileOutputStream(file))
118+
zout = ZipOutputStream(fout)
119+
120+
# Use a fixed name for the XML inside the ZIP
121+
entry = ZipEntry("process.xml")
122+
zout.putNextEntry(entry)
123+
124+
writer = OutputStreamWriter(zout, "UTF-8")
125+
xstream.toXML(javaobject, writer)
126+
writer.flush()
127+
zout.closeEntry()
128+
writer.close()
129+
zout.close()
130+
131+
return True
132+
except Exception as e:
133+
print(f"Error saving NEQSim object to ZIP: {e}")
134+
return False
135+
136+
143137
def save_xml(javaobject, filename):
144138
xstream = jpype.JPackage("com.thoughtworks.xstream")
145139
streamer = xstream.XStream()

tests/process/test_ProcessTools.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,13 @@ def test_gasoilprocess():
418418

419419
runProcess()
420420

421+
from neqsim import save_neqsim, open_neqsim
422+
from neqsim.process import getProcess
423+
save_neqsim(getProcess(), "test_gasoilprocess.zip")
424+
425+
process1 = open_neqsim("test_gasoilprocess.zip")
426+
process1.run()
427+
421428
# assert 3859.9 == approx(recirc1stream.getFlowRate('kg/hr'), abs=1.0)
422429
# assert 22876.1 == approx(pipeloss1st.getOutletStream().getFlowRate("kg/hr"), abs=1.0)
423430
# assert separator3.getGasOutStream().getFlowRate("kg/hr") == pipeloss1st.getOutletStream().getFlowRate("kg/hr")

0 commit comments

Comments
 (0)