Starting with Jep 3.1, parsed expressions, the main Jep class, and its sub-components are all serializable. This allows persistent storage and transfer between applications. Issues regarding threads and the use of multiple Jep instances are also discussed in this section.
Depending on your needs you may choose from three different serialization options:
The Node class itself is not serializable. Instead, a wrapper class
com.singularsys.jep.walkers.SerializableExpression
is used to provide a compact serializable representation of a node. The class is constructed
using new SerializedExpression(Node n)
and the Node toNode(Jep j)
method is used to extract the node in the context
of a given Jep instance.
To serialize use:
// Set-up jep Jep j = new Jep(); // create an ObjectOutputStream ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); // parse an expression Node n = j.parse("1+cos(2 th)"); // Create a SerializableExpression SerializableExpression se = new SerializableExpression(n); // write the SerializedExpression oos.writeObject(se); oos.close(); // extract the bytes byte bytes[] = baos.toByteArray();
To deserialize the expression use:
// Set-up jep Jep j2 = new Jep(); // Create an ObjectInputStream from the set of bytes ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); // Deserialize the SerializableExpression SerializableExpression se2 = (SerializableExpression) ois.readObject(); // Create a node Node n2 = se2.toNode(j2); ois.close();
Alternatively, the serialized expression could be written to a file
.... File f = new File(....); FileOutputStream fos = new FileOutputStream(f); ObjectOutputStream oos = new ObjectOutputStream(fos); // write objects oos.writeObject(se); oos.close();
FileInputStream fis = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(fis); // read objects SerializableExpression se2 = (SerializableExpression) ois.readObject(); ois.close();
If you wish to serialize the values of variables for later use, then the VariableTable can be serialized. Again this methods assumes the same version and configuration of the Jep instances.
Jep j = new Jep(); // Setup the ObjectOutputStream ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); // Serialize the VariableTable oos.writeObject(j.getVariableTable()); // Serialize the expression Node n = j.parse("a+cos(2 th)"); SerializableExpression se = new SerializableExpression(n); oos.writeObject(se); oos.close(); byte bytes[] = baos.toByteArray();
To deserialize
// Set-up jep Jep j2 = new Jep(); // Create an ObjectInputStream ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); // Deserialize the SymbolTable VariableTable vt2 = (VariableTable) ois.readObject(); // Set the SymbolTable as that used by the jep instance j2.setComponent(vt2); // Deserialize the expression SerializableExpression se2 = (SerializableExpression) ois.readObject(); Node n2 = se2.toNode(j2); ois.close();
The Jep class and all its components are serializable, meaning that the configuration of the Jep instance can be stored. This includes the full set of variables, functions, operators, and various settings. If the ConfigurableParser is used, then its configuration is also stored. Note that changes made to the standard JavaCC parser are not recorded.
A typical setup will take 7KB with the standard parser and 12KB with the configurable parser.
Jep j = new Jep(); // Setup the ObjectOutputStream ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); // Serialize the VariableTable oos.writeObject(j); // Serialize the expression Node n = j.parse("a+cos(2 th)"); SerializableExpression se = new SerializableExpression(n); oos.writeObject(se); oos.close(); byte bytes[] = baos.toByteArray();
To deserialize
// Create an ObjectInputStream from the set of bytes ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); // Deserialize the Jep instance Jep j2 = (Jep) ois.readObject(); // Deserialize the expression SerializableExpression se2 = (SerializableExpression) ois.readObject(); Node n2 = se2.toNode(j2); ois.close();
The SerializedExpression class can also be used to produce copies of a node without having to serialize and deserialize.
// Create first instance Jep j = new Jep(); // Parse equation using first instance Node n = j.parse("a+cos(2 th)"); // Create a SerializableExpression SerializableExpression se = new SerializableExpression(n); // Create second instance Jep j2 = new Jep(); // Import expression into second instance Node n2 = se.toNode(j2);
An alternative method is to use an ImportationVisitor which is a bit faster but cannot handle as large equations.