docs: update slob

This commit is contained in:
Ilkka Seppälä
2024-05-20 10:57:38 +03:00
parent cfb09c1358
commit 292554e76e
17 changed files with 262 additions and 356 deletions
@@ -0,0 +1,144 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.slob;
import com.iluwatar.slob.lob.Animal;
import com.iluwatar.slob.lob.Forest;
import com.iluwatar.slob.lob.Plant;
import com.iluwatar.slob.serializers.BlobSerializer;
import com.iluwatar.slob.serializers.ClobSerializer;
import com.iluwatar.slob.serializers.LobSerializer;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
* SLOB Application using {@link LobSerializer} and H2 DB.
*/
public class App {
public static final String CLOB = "CLOB";
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/**
* Main entry point to program.
* <p>In the SLOB pattern, the object graph is serialized into a single large object (a BLOB or
* CLOB, for Binary Large Object or Character Large Object, respectively) and stored in the
* database. When the object graph needs to be retrieved, it is read from the database and
* deserialized back into the original object graph.</p>
*
* <p>A Forest is created using {@link #createForest()} with Animals and Plants along with their
* respective relationships.</p>
*
* <p>Creates a {@link LobSerializer} using the method
* {@link #createLobSerializer(String[])}.</p>
*
* <p>Once created the serializer is passed to the
* {@link #executeSerializer(Forest, LobSerializer)} which handles the serialization,
* deserialization and persisting and loading from DB.</p>
*
* @param args if first arg is CLOB then ClobSerializer is used else BlobSerializer is used.
*/
public static void main(String[] args) throws SQLException {
Forest forest = createForest();
LobSerializer serializer = createLobSerializer(args);
executeSerializer(forest, serializer);
}
/**
* <p>Creates a {@link LobSerializer} on the basis of input args. </p>
* <p>If input args are not empty and the value equals {@link App#CLOB} then a
* {@link ClobSerializer} is created else a {@link BlobSerializer} is created.</p>
*
* @param args if first arg is {@link App#CLOB} then ClobSerializer is instantiated else
* BlobSerializer is instantiated.
*/
private static LobSerializer createLobSerializer(String[] args) throws SQLException {
LobSerializer serializer;
if (args.length > 0 && Objects.equals(args[0], CLOB)) {
serializer = new ClobSerializer();
} else {
serializer = new BlobSerializer();
}
return serializer;
}
/**
* Creates a Forest with {@link Animal} and {@link Plant} along with their respective
* relationships.
*
* <p> The method creates a {@link Forest} with 2 Plants Grass and Oak of type Herb and tree
* respectively.</p>
*
* <p> It also creates 3 animals Zebra and Buffalo which eat the plant grass. Lion consumes the
* Zebra and the Buffalo.</p>
*
* <p>With the above animals and plants and their relationships a forest
* object is created which represents the Object Graph.</p>
*
* @return Forest Object
*/
private static Forest createForest() {
Plant grass = new Plant("Grass", "Herb");
Plant oak = new Plant("Oak", "Tree");
Animal zebra = new Animal("Zebra", Set.of(grass), Collections.emptySet());
Animal buffalo = new Animal("Buffalo", Set.of(grass), Collections.emptySet());
Animal lion = new Animal("Lion", Collections.emptySet(), Set.of(zebra, buffalo));
return new Forest("Amazon", Set.of(lion, buffalo, zebra), Set.of(grass, oak));
}
/**
* Serialize the input object using the input serializer and persist to DB. After this it loads
* the same object back from DB and deserializes using the same serializer.
*
* @param forest Object to Serialize and Persist
* @param lobSerializer Serializer to Serialize and Deserialize Object
*/
private static void executeSerializer(Forest forest, LobSerializer lobSerializer) {
try (LobSerializer serializer = lobSerializer) {
Object serialized = serializer.serialize(forest);
int id = serializer.persistToDb(1, forest.getName(), serialized);
Object fromDb = serializer.loadFromDb(id, Forest.class.getSimpleName());
Forest forestFromDb = serializer.deSerialize(fromDb);
LOGGER.info(forestFromDb.toString());
} catch (SQLException | IOException | TransformerException | ParserConfigurationException
| SAXException
| ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,157 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.slob.dbservice;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.h2.jdbcx.JdbcDataSource;
/**
* Service to handle database operations.
*/
@Slf4j
public class DatabaseService {
public static final String CREATE_BINARY_SCHEMA_DDL =
"CREATE TABLE IF NOT EXISTS FORESTS (ID NUMBER UNIQUE, NAME VARCHAR(30),FOREST VARBINARY)";
public static final String CREATE_TEXT_SCHEMA_DDL =
"CREATE TABLE IF NOT EXISTS FORESTS (ID NUMBER UNIQUE, NAME VARCHAR(30),FOREST VARCHAR)";
public static final String DELETE_SCHEMA_SQL = "DROP TABLE FORESTS IF EXISTS";
public static final String BINARY_DATA = "BINARY";
private static final String DB_URL = "jdbc:h2:~/test";
private static final String INSERT = "insert into FORESTS (id,name, forest) values (?,?,?)";
private static final String SELECT = "select FOREST from FORESTS where id = ?";
private static final DataSource dataSource = createDataSource();
public String dataTypeDb;
/**
* Constructor initializes {@link DatabaseService#dataTypeDb}.
*
* @param dataTypeDb Type of data that is to be stored in DB can be 'TEXT' or 'BINARY'.
*/
public DatabaseService(String dataTypeDb) {
this.dataTypeDb = dataTypeDb;
}
/**
* Initiates Data source.
*
* @return created data source
*/
private static DataSource createDataSource() {
var dataSource = new JdbcDataSource();
dataSource.setURL(DB_URL);
return dataSource;
}
/**
* Shutdown Sequence executes Query {@link DatabaseService#DELETE_SCHEMA_SQL}.
*
* @throws SQLException if any issue occurs while executing DROP Query
*/
public void shutDownService()
throws SQLException {
try (var connection = dataSource.getConnection();
var statement = connection.createStatement()) {
statement.execute(DELETE_SCHEMA_SQL);
}
}
/**
* Initaites startup sequence and executes the query
* {@link DatabaseService#CREATE_BINARY_SCHEMA_DDL} if {@link DatabaseService#dataTypeDb} is
* binary else will execute the query {@link DatabaseService#CREATE_TEXT_SCHEMA_DDL}.
*
* @throws SQLException if there are any issues during DDL execution
*/
public void startupService()
throws SQLException {
try (var connection = dataSource.getConnection();
var statement = connection.createStatement()) {
if (dataTypeDb.equals("BINARY")) {
statement.execute(CREATE_BINARY_SCHEMA_DDL);
} else {
statement.execute(CREATE_TEXT_SCHEMA_DDL);
}
}
}
/**
* Executes the insert query {@link DatabaseService#INSERT}.
*
* @param id with which row is to be inserted
* @param name name to be added in the row
* @param data object data to be saved in the row
* @throws SQLException if there are any issues in executing insert query
* {@link DatabaseService#INSERT}
*/
public void insert(int id, String name, Object data)
throws SQLException {
try (var connection = dataSource.getConnection();
var insert = connection.prepareStatement(INSERT)) {
insert.setInt(1, id);
insert.setString(2, name);
insert.setObject(3, data);
insert.execute();
}
}
/**
* Runs the select query {@link DatabaseService#SELECT} form the result set returns an
* {@link java.io.InputStream} if {@link DatabaseService#dataTypeDb} is 'binary' else will return
* the object as a {@link String}.
*
* @param id with which row is to be selected
* @param columnsName column in which the object is stored
* @return object found from DB
* @throws SQLException if there are any issues in executing insert query *
* {@link DatabaseService#SELECT}
*/
public Object select(final long id, String columnsName) throws SQLException {
ResultSet resultSet = null;
try (var connection = dataSource.getConnection();
var preparedStatement =
connection.prepareStatement(SELECT)
) {
Object result = null;
preparedStatement.setLong(1, id);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
if (dataTypeDb.equals(BINARY_DATA)) {
result = resultSet.getBinaryStream(columnsName);
} else {
result = resultSet.getString(columnsName);
}
}
return result;
} finally {
if (resultSet != null) {
resultSet.close();
}
}
}
}
@@ -0,0 +1,131 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.slob.lob;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Creates an object Animal with a list of animals and/or plants it consumes.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Animal implements Serializable {
private String name;
private Set<Plant> plantsEaten = new HashSet<>();
private Set<Animal> animalsEaten = new HashSet<>();
/**
* Iterates over the input nodes recursively and adds new plants to {@link Animal#plantsEaten} or
* animals to {@link Animal#animalsEaten} found to input sets respectively.
*
* @param childNodes contains the XML Node containing the Forest
* @param animalsEaten set of Animals eaten
* @param plantsEaten set of Plants eaten
*/
protected static void iterateXmlForAnimalAndPlants(NodeList childNodes, Set<Animal> animalsEaten,
Set<Plant> plantsEaten) {
for (int i = 0; i < childNodes.getLength(); i++) {
Node child = childNodes.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
if (child.getNodeName().equals(Animal.class.getSimpleName())) {
Animal animalEaten = new Animal();
animalEaten.createObjectFromXml(child);
animalsEaten.add(animalEaten);
} else if (child.getNodeName().equals(Plant.class.getSimpleName())) {
Plant plant = new Plant();
plant.createObjectFromXml(child);
plantsEaten.add(plant);
}
}
}
}
/**
* Provides XML Representation of the Animal.
*
* @param xmlDoc object to which the XML representation is to be written to
* @return XML Element contain the Animal representation
*/
public Element toXmlElement(Document xmlDoc) {
Element root = xmlDoc.createElement(Animal.class.getSimpleName());
root.setAttribute("name", name);
for (Plant plant : plantsEaten) {
Element xmlElement = plant.toXmlElement(xmlDoc);
if (xmlElement != null) {
root.appendChild(xmlElement);
}
}
for (Animal animal : animalsEaten) {
Element xmlElement = animal.toXmlElement(xmlDoc);
if (xmlElement != null) {
root.appendChild(xmlElement);
}
}
xmlDoc.appendChild(root);
return (Element) xmlDoc.getFirstChild();
}
/**
* Parses the Animal Object from the input XML Node.
*
* @param node the XML Node from which the Animal Object is to be parsed
*/
public void createObjectFromXml(Node node) {
name = node.getAttributes().getNamedItem("name").getNodeValue();
NodeList childNodes = node.getChildNodes();
iterateXmlForAnimalAndPlants(childNodes, animalsEaten, plantsEaten);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\nAnimal Name = ").append(name);
if (!animalsEaten.isEmpty()) {
sb.append("\n\tAnimals Eaten by ").append(name).append(": ");
}
for (Animal animal : animalsEaten) {
sb.append("\n\t\t").append(animal);
}
sb.append("\n");
if (!plantsEaten.isEmpty()) {
sb.append("\n\tPlants Eaten by ").append(name).append(": ");
}
for (Plant plant : plantsEaten) {
sb.append("\n\t\t").append(plant);
}
return sb.toString();
}
}
@@ -0,0 +1,121 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.slob.lob;
import static com.iluwatar.slob.lob.Animal.iterateXmlForAnimalAndPlants;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Creates an object Forest which contains animals and plants as its constituents. Animals may eat
* plants or other animals in the forest.
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Forest implements Serializable {
private String name;
private Set<Animal> animals = new HashSet<>();
private Set<Plant> plants = new HashSet<>();
/**
* Provides the representation of Forest in XML form.
*
* @return XML Element
*/
public Element toXmlElement() throws ParserConfigurationException {
Document xmlDoc = getXmlDoc();
Element forestXml = xmlDoc.createElement("Forest");
forestXml.setAttribute("name", name);
Element animalsXml = xmlDoc.createElement("Animals");
for (Animal animal : animals) {
Element animalXml = animal.toXmlElement(xmlDoc);
animalsXml.appendChild(animalXml);
}
forestXml.appendChild(animalsXml);
Element plantsXml = xmlDoc.createElement("Plants");
for (Plant plant : plants) {
Element plantXml = plant.toXmlElement(xmlDoc);
plantsXml.appendChild(plantXml);
}
forestXml.appendChild(plantsXml);
return forestXml;
}
/**
* Returns XMLDoc to use for XML creation.
*
* @return XML DOC Object
* @throws ParserConfigurationException {@inheritDoc}
*/
private Document getXmlDoc() throws ParserConfigurationException {
return DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder().newDocument();
}
/**
* Parses the Forest Object from the input XML Document.
*
* @param document the XML document from which the Forest is to be parsed
*/
public void createObjectFromXml(Document document) {
name = document.getDocumentElement().getAttribute("name");
NodeList nodeList = document.getElementsByTagName("*");
iterateXmlForAnimalAndPlants(nodeList, animals, plants);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("\n");
sb.append("Forest Name = ").append(name).append("\n");
sb.append("Animals found in the ").append(name).append(" Forest: \n");
for (Animal animal : animals) {
sb.append("\n--------------------------\n");
sb.append(animal.toString());
sb.append("\n--------------------------\n");
}
sb.append("\n");
sb.append("Plants in the ").append(name).append(" Forest: \n");
for (Plant plant : plants) {
sb.append("\n--------------------------\n");
sb.append(plant.toString());
sb.append("\n--------------------------\n");
}
return sb.toString();
}
}
@@ -0,0 +1,80 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.slob.lob;
import java.io.Serializable;
import java.util.StringJoiner;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* Creates an object Plant which contains its name and type.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Plant implements Serializable {
private String name;
private String type;
/**
* Provides XML Representation of the Plant.
*
* @param xmlDoc to which the XML representation is to be written to
* @return XML Element contain the Animal representation
*/
public Element toXmlElement(Document xmlDoc) {
Element root = xmlDoc.createElement(Plant.class.getSimpleName());
root.setAttribute("name", name);
root.setAttribute("type", type);
xmlDoc.appendChild(root);
return xmlDoc.getDocumentElement();
}
/**
* Parses the Plant Object from the input XML Node.
*
* @param node the XML Node from which the Animal Object is to be parsed
*/
public void createObjectFromXml(Node node) {
NamedNodeMap attributes = node.getAttributes();
name = attributes.getNamedItem("name").getNodeValue();
type = attributes.getNamedItem("type").getNodeValue();
}
@Override
public String toString() {
StringJoiner stringJoiner = new StringJoiner(",");
stringJoiner.add("Name = " + name);
stringJoiner.add("Type = " + type);
return stringJoiner.toString();
}
}
@@ -0,0 +1,83 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.slob.serializers;
import com.iluwatar.slob.lob.Forest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.SQLException;
/**
* Creates a Serializer that uses Binary serialization and deserialization of objects graph to and
* from their Binary Representation.
*/
public class BlobSerializer extends LobSerializer {
public static final String TYPE_OF_DATA_FOR_DB = "BINARY";
public BlobSerializer() throws SQLException {
super(TYPE_OF_DATA_FOR_DB);
}
/**
* Serializes the input object graph to its Binary Representation using Object Stream.
*
* @param toSerialize Object which is to be serialized
* @return Serialized object
* @throws IOException {@inheritDoc}
*/
@Override
public Object serialize(Forest toSerialize) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(toSerialize);
oos.close();
return new ByteArrayInputStream(baos.toByteArray());
}
/**
* Deserializes the input Byte Array Stream using Object Stream and return its Object Graph
* Representation.
*
* @param toDeserialize Input Object to De-serialize
* @return Deserialized Object
* @throws ClassNotFoundException {@inheritDoc}
* @throws IOException {@inheritDoc}
*/
@Override
public Forest deSerialize(Object toDeserialize) throws IOException, ClassNotFoundException {
InputStream bis = (InputStream) toDeserialize;
Forest forest;
try (ObjectInput in = new ObjectInputStream(bis)) {
forest = (Forest) in.readObject();
}
return forest;
}
}
@@ -0,0 +1,107 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.slob.serializers;
import com.iluwatar.slob.lob.Forest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.sql.SQLException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/**
* Creates a Serializer that uses Character based serialization and deserialization of objects graph
* to and from XML Representation.
*/
public class ClobSerializer extends LobSerializer {
public static final String TYPE_OF_DATA_FOR_DB = "TEXT";
public ClobSerializer() throws SQLException {
super(TYPE_OF_DATA_FOR_DB);
}
/**
* Converts the input node to its XML String Representation.
*
* @param node XML Node that is to be converted to string
* @return String representation of XML parsed from the Node
* @throws TransformerException If any issues occur in Transformation from Node to XML
*/
private static String elementToXmlString(Element node) throws TransformerException {
StringWriter sw = new StringWriter();
Transformer t = TransformerFactory.newDefaultInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(new DOMSource(node), new StreamResult(sw));
return sw.toString();
}
/**
* Serializes the input object graph to its XML Representation using DOM Elements.
*
* @param forest Object which is to be serialized
* @return Serialized object
* @throws ParserConfigurationException If any issues occur in parsing input object
* @throws TransformerException If any issues occur in Transformation from Node to XML
*/
@Override
public Object serialize(Forest forest) throws ParserConfigurationException, TransformerException {
Element xmlElement = forest.toXmlElement();
return elementToXmlString(xmlElement);
}
/**
* Deserializes the input XML string using DOM Parser and return its Object Graph Representation.
*
* @param toDeserialize Input Object to De-serialize
* @return Deserialized Object
* @throws ParserConfigurationException If any issues occur in parsing input object
* @throws IOException if any issues occur during reading object
* @throws SAXException If any issues occur in Transformation from Node to XML
*/
@Override
public Forest deSerialize(Object toDeserialize)
throws ParserConfigurationException, IOException, SAXException {
DocumentBuilder documentBuilder = DocumentBuilderFactory.newDefaultInstance()
.newDocumentBuilder();
var stream = new ByteArrayInputStream(toDeserialize.toString().getBytes());
Document parsed = documentBuilder.parse(stream);
Forest forest = new Forest();
forest.createObjectFromXml(parsed);
return forest;
}
}
@@ -0,0 +1,115 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.slob.serializers;
import com.iluwatar.slob.dbservice.DatabaseService;
import com.iluwatar.slob.lob.Forest;
import java.io.Closeable;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.xml.sax.SAXException;
/**
* A LobSerializer can be used to create an instance of a serializer which can serialize and
* deserialize an object and persist and load that object into a DB. from their Binary
* Representation.
*/
public abstract class LobSerializer implements Serializable, Closeable {
private final transient DatabaseService databaseService;
/**
* Constructor initializes {@link LobSerializer#databaseService}.
*
* @param dataTypeDb Input provides type of Data to be stored by the Data Base Service
* @throws SQLException If any issue occurs during instantiation of DB Service or during startup.
*/
protected LobSerializer(String dataTypeDb) throws SQLException {
databaseService = new DatabaseService(dataTypeDb);
databaseService.startupService();
}
/**
* Provides the specification to Serialize the input object.
*
* @param toSerialize Input Object to serialize
* @return Serialized Object
* @throws ParserConfigurationException if any issue occurs during parsing of input object
* @throws TransformerException if any issue occurs during Transformation
* @throws IOException if any issues occur during reading object
*/
public abstract Object serialize(Forest toSerialize)
throws ParserConfigurationException, TransformerException, IOException;
/**
* Saves the object to DB with the provided ID.
*
* @param id key to be sent to DB service
* @param name Object name to store in DB
* @param object Object to store in DB
* @return ID with which the object is stored in DB
* @throws SQLException if any issue occurs while saving to DB
*/
public int persistToDb(int id, String name, Object object) throws SQLException {
databaseService.insert(id, name, object);
return id;
}
/**
* Loads the object from db using the ID and column name.
*
* @param id to query the DB
* @param columnName column from which object is to be extracted
* @return Object from DB
* @throws SQLException if any issue occurs while loading from DB
*/
public Object loadFromDb(int id, String columnName) throws SQLException {
return databaseService.select(id, columnName);
}
/**
* Provides the specification to Deserialize the input object.
*
* @param toDeserialize object to deserialize
* @return Deserialized Object
* @throws ParserConfigurationException If issue occurs during parsing of input object
* @throws IOException if any issues occur during reading object
* @throws SAXException if any issues occur during reading object for XML parsing
*/
public abstract Forest deSerialize(Object toDeserialize)
throws ParserConfigurationException, IOException, SAXException, ClassNotFoundException;
@Override
public void close() {
try {
databaseService.shutDownService();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}