package com.horstmann.violet.framework.file.persistence;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.beans.DefaultPersistenceDelegate;
import java.beans.Encoder;
import java.beans.ExceptionListener;
import java.beans.Statement;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.horstmann.violet.framework.injection.bean.ManiocFramework.ManagedBean;
import com.horstmann.violet.product.diagram.property.BentStyleChoiceList;
import com.horstmann.violet.product.diagram.property.LineStyleChoiceList;
import com.horstmann.violet.product.diagram.abstracts.AbstractGraph;
import com.horstmann.violet.product.diagram.abstracts.IGraph;
import com.horstmann.violet.product.diagram.abstracts.Id;
import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
import com.horstmann.violet.product.diagram.abstracts.node.AbstractNode;
import com.horstmann.violet.product.diagram.abstracts.node.INode;
import com.horstmann.violet.product.diagram.property.ArrowheadChoiceList;
import com.horstmann.violet.product.diagram.common.node.ImageNode;
/**
* Standard Java implementation of IFilePersistenceService
* @author alex
*
*/
@ManagedBean(registeredManually=true)
public class StandardJavaFilePersistenceService implements IFilePersistenceService
{
@Override
public void write(IGraph graph, OutputStream out)
{
XMLEncoder encoder = getXMLEncoder(Violet016BackportFormatService.convertToViolet016(out));
encoder.writeObject(graph);
encoder.close();
}
@Override
public IGraph read(InputStream in) throws IOException
{
XMLDecoder reader = new XMLDecoder(Violet016BackportFormatService.convertFromViolet016(in), null, new ExceptionListener()
{
public void exceptionThrown(Exception e)
{
e.printStackTrace();
}
});
IGraph graph = (IGraph) reader.readObject();
in.close();
return graph;
}
/**
* Creates a new instance of XML Encoder pre-configured for Violet beans serailization
*
* @param out
* @return configured encoder
*/
private XMLEncoder getXMLEncoder(OutputStream out)
{
XMLEncoder encoder = new XMLEncoder(out);
encoder.setExceptionListener(new ExceptionListener()
{
public void exceptionThrown(Exception ex)
{
ex.printStackTrace();
}
});
configure(encoder);
return encoder;
}
/**
* Configures the given XML encoder by setting custom persistenceDelegate
* @param encoder
*/
private void configure(XMLEncoder encoder)
{
encoder.setPersistenceDelegate(Point2D.Double.class, new DefaultPersistenceDelegate()
{
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
{
super.initialize(type, oldInstance, newInstance, out);
Point2D p = (Point2D) oldInstance;
out.writeStatement(new Statement(oldInstance, "setLocation", new Object[]
{
new Double(p.getX()),
new Double(p.getY())
}));
}
});
encoder.setPersistenceDelegate(Line2D.class, new DefaultPersistenceDelegate()
{
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
{
super.initialize(type, oldInstance, newInstance, out);
Line2D l = (Line2D) oldInstance;
out.writeStatement(new Statement(oldInstance, "setLine", new Object[]
{
new Double(l.getX1()),
new Double(l.getY1()),
new Double(l.getX2()),
new Double(l.getY2())
}));
}
});
encoder.setPersistenceDelegate(Rectangle2D.class, new DefaultPersistenceDelegate()
{
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
{
super.initialize(type, oldInstance, newInstance, out);
Rectangle2D r = (Rectangle2D) oldInstance;
out.writeStatement(new Statement(oldInstance, "setRect", new Object[]
{
new Double(r.getX()),
new Double(r.getY()),
new Double(r.getWidth()),
new Double(r.getHeight())
}));
}
});
encoder.setPersistenceDelegate(BentStyleChoiceList.class, new CustomPersistenceDelegate());
encoder.setPersistenceDelegate(LineStyleChoiceList.class, new CustomPersistenceDelegate());
encoder.setPersistenceDelegate(ArrowheadChoiceList.class, new CustomPersistenceDelegate());
encoder.setPersistenceDelegate(URL.class, new DefaultPersistenceDelegate(new String[]
{
"protocol",
"host",
"port",
"file"
}));
encoder.setPersistenceDelegate(Map.class, new DefaultPersistenceDelegate()
{
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
{
super.initialize(type, oldInstance, newInstance, out);
Map<?, ?> map = (Map<?, ?>) oldInstance;
for (Iterator<?> it = map.keySet().iterator(); it.hasNext();)
{
Object key = it.next();
Object value = map.get(key);
out.writeStatement(new Statement(oldInstance, "put", new Object[]
{
key,
value
}));
}
}
});
encoder.setPersistenceDelegate(AbstractNode.class, new DefaultPersistenceDelegate()
{
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
{
super.initialize(type, oldInstance, newInstance, out);
INode n = (INode) oldInstance;
List<INode> children = new ArrayList<INode>(n.getChildren());
for (int i = 0; i < children.size(); i++)
{
INode c = (INode) children.get(i);
Point2D p = c.getLocation();
out.writeStatement(new Statement(oldInstance, "addChild", new Object[]
{
c,
p
}));
}
boolean isWriteId = false; // Keep for further refinement
if (isWriteId)
{
Id id = n.getId();
out.writeStatement(new Statement(oldInstance, "setId", new Object[]
{
id
}));
}
}
});
encoder.setPersistenceDelegate(AbstractGraph.class, new DefaultPersistenceDelegate()
{
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
{
super.initialize(type, oldInstance, newInstance, out);
AbstractGraph g = (AbstractGraph) oldInstance;
for ( INode n : g.getAllNodes())
{
INode parent = n.getParent();
if (parent != null) continue;
Point2D p = n.getLocation();
out.writeStatement(new Statement(oldInstance, "addNode", new Object[]
{
n,
p
}));
}
for (IEdge e : g.getAllEdges())
{
out.writeStatement(new Statement(oldInstance, "connect", new Object[]
{
e,
e.getStartNode(),
e.getStartLocation(),
e.getEndNode(),
e.getEndLocation()
}));
}
}
});
// encoder.setPersistenceDelegate(AbstractEdge.class, new DefaultPersistenceDelegate()
// {
// protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
// {
// super.initialize(type, oldInstance, newInstance, out);
// IEdge e = (IEdge) oldInstance;
// out.writeStatement(new Statement(oldInstance, "connect", new Object[]
// {
// e.getStartNode(),
// e.getEndNode()
// }));
// }
// });
encoder.setPersistenceDelegate(ImageNode.class, new DefaultPersistenceDelegate()
{
protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
{
super.initialize(type, oldInstance, newInstance, out);
ImageNode n = (ImageNode) oldInstance;
try
{
String imageContent = n.getImageContent();
int width = n.getImageWidth();
int height = n.getImageHeight();
out.writeStatement(new Statement(oldInstance, "setImageContent", new Object[]
{
imageContent,
width,
height
}));
}
catch (InterruptedException e)
{
throw new RuntimeException("Error while serializing ImageNode", e);
}
}
});
}
}