All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgraph.pad.DefaultGraphModelFileFormatXML Maven / Gradle / Ivy

There is a newer version: 0.4.7
Show newest version
/*
 * @(#)DefaultGraphModelFileFormatXML.java	1.0 17.02.2003
 *
 * Copyright (C) 2003 sven.luzar
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
package org.jgraph.pad;

import org.jgpd.io.JGpdModelNode;
import org.jgpd.io.ModelImportImpl;
import org.jgpd.io.jbpm.ModelImportJBpm;
import org.jgpd.jgraph.*;
import org.jgraph.graph.*;
import org.jgraph.pad.resources.Translator;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.filechooser.FileFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.awt.*;
import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.List;
import java.util.*;

/**File format for the default graph model.
 * The file format writes a XML
 * file with the graph as content.
 *
 * @author luzar
 * @version 1.0
 */
public class DefaultGraphModelFileFormatXML implements GraphModelFileFormat {

	public static final String EMPTY = new String("Empty");

	public static final String PARENT = new String("Parent");

	protected static Map cells = new Hashtable();

	protected static Map attrs = new Hashtable();

	protected static Map objs = new Hashtable();

	protected static List delayedAttributes = new LinkedList();

	protected static List connectionSetIDs = new LinkedList();

	protected Map cellMap = new Hashtable();

	protected static ModelImportImpl importModel;

    	protected AttributeCollection attrCol = new AttributeCollection();

	protected Map userObjectMap = new Hashtable();

	/** file filter for this file format
	 */
	FileFilter fileFilter;

	/** accessory component. A checkbox for the
	 *  zipped output or unzipped output
	 *
	 */
	JComponent compZipSelect;

	/** a const value for the key at the properties hashtable
	 */
	public static final String COMPRESS_WITH_ZIP = "CompressWithZip";

	/**
	 * Constructor for DefaultGraphModelFileFormatXML.
	 */
	public DefaultGraphModelFileFormatXML() {
		if (importModel == null )
		{
			importModel = new ModelImportJBpm(); // FIXME needs to be model independant
		}

		fileFilter = new FileFilter() {
			/**
			 * @see FileFilter#accept(File)
			 */
			public boolean accept(File f) {
				if (f == null)
					return false;
				if (f.getName() == null)
					return false;
				if (f.getName().endsWith(".gpd"))
					return true;
				if (f.isDirectory())
					return true;

				return false;
			}

			/**
			 * @see FileFilter#getDescription()
			 */
			public String getDescription() {
				return Translator.getString("FileDesc.JGpdDiagramXml"); /*Finished: Original="JGraphpad Diagram (*.pad_xml)"*/
			}
		};
		compZipSelect = new JCheckBox(Translator.getString("zipCompress"));
	}

	/** returns pad_xml
	 */
	public String getFileExtension(){
		return "gpd";
	}


	/** Returns a file filter for the pad_xml extension.
	 *
	 * @see GraphModelFileFormat#getFileFilter()
	 */
	public FileFilter getFileFilter() {
		return fileFilter;
	}

	/** Returns null
	 * @see GraphModelFileFormat#getReadAccessory()
	 */
	public JComponent getReadAccessory() {
		return null;
	}

	/** Returns the compZipSelect object.
	 *
	 * @see #compZipSelect
	 * @see GraphModelFileFormat#getWriteAccessory()
	 */
	public JComponent getWriteAccessory() {
	    return null; //compZipSelect;
	}

	/**
	 * Writes the graph as XML file
	 *
	 */
	public void write(
		URL file,
		Hashtable properties,
		GPGraph gpGraph,
		GraphModel graphModel)
		throws Exception {

		// don't try / catch this command
		// sothat we get error messages at the
		// frontend.
		// e.g. I you have not permissions to
		// write a file you should get an error message

		//try {
			OutputStream out = null;
			out = new FileOutputStream(file.getFile());
// Ignore
// 		if (properties != null &&
// 			properties.get(COMPRESS_WITH_ZIP) != null &&
// 			((Boolean)properties.get(COMPRESS_WITH_ZIP)).booleanValue() )
// 			f = new GZIPOutputStream(f);
			out = new BufferedOutputStream(out);
			out.write(toString(gpGraph).getBytes());
			out.flush();
			out.close();

		//} catch (Exception e) {
		//	e.printStackTrace();
		//}

	}

	/**
	 * Puts the value from the checkbox into the properties hashtable
	 *
	 * @see GraphModelFileFormat#getWriteProperties(JComponent)
	 */
	public Hashtable getWriteProperties(JComponent accessory) {
		Hashtable properties = new Hashtable();
		if (!(accessory instanceof JCheckBox)){
			return properties;
		}
		properties.put(COMPRESS_WITH_ZIP, new Boolean(((JCheckBox)accessory).isSelected() ));
		return properties;
	}

	/**Reads the File form the XML input stream.
	 * Tempts to load from a zipped input stream.
	 * If this procedure fails the method tempts
	 * to load without the zipped option.
	 *
	 */
	public GraphModel read(
		URL file,
		Hashtable properties,
		GPGraph gpGraph)
		throws Exception {

	    // Check file contents for new file format
	    boolean newFileFormat = false;
	    try {
		    InputStream f = file.openStream();
		    byte[] ident = new byte[4];
		    int length = f.read(ident);
		    if (length == 4 && new String(ident).toLowerCase().equals(" 0) {
					if (pid != null)
						attrs.put(
							PARENT,
							pid.getNodeValue());
					map.put(key.getNodeValue(), attrs);
				}
			}
		}
		return map;
	}

	/**
	 * Returns an attributeMap for the specified position and color.
	 */
	public static Map createDefaultAttributes() {
		// Create an AttributeMap
		Map map = GraphConstants.createMap();
		// Set a Black Line Border (the Border-Attribute must be Null!)
		GraphConstants.setBorderColor(map, Color.black);
		// Return the Map
		return map;
	}

	public static class DelayedAttributeID {

		protected Object cell;

		protected Rectangle bounds;

		protected List points;

		protected String mapID;

		public DelayedAttributeID(
			Object cell,
			Rectangle bounds,
			List points,
			String mapID) {
			this.cell = cell;
			this.bounds = bounds;
			this.points = points;
			this.mapID = mapID;
		}

		/**
		 * @return
		 */
		public Object getCell() {
			return cell;
		}

		/**
		 * @return
		 */
		public Rectangle getBounds() {
			return bounds;
		}

		/**
		 * @return
		 */
		public String getMapID() {
			return mapID;
		}

		/**
		 * @return
		 */
		public List getPoints() {
			return points;
		}

		/**
		 * @param rectangle
		 */
		public void setBounds(Rectangle rectangle) {
			bounds = rectangle;
		}

		/**
		 * @param object
		 */
		public void setCell(Object object) {
			cell = object;
		}

		/**
		 * @param string
		 */
		public void setMapID(String string) {
			mapID = string;
		}

		/**
		 * @param list
		 */
		public void setPoints(List list) {
			points = list;
		}

	}

	public static class ConnectionID {

		protected Object cell;

		protected String targetID;

		protected boolean source;

		public ConnectionID(Object cell, String targetID, boolean source) {
			this.cell = cell;
			this.targetID = targetID;
			this.source = source;
		}

		/**
		 * @return
		 */
		public Object getCell() {
			return cell;
		}

		/**
		 * @return
		 */
		public boolean isSource() {
			return source;
		}

		/**
		 * @return
		 */
		public String getTargetID() {
			return targetID;
		}

		/**
		 * @param object
		 */
		public void setCell(Object object) {
			cell = object;
		}

		/**
		 * @param b
		 */
		public void setSource(boolean b) {
			source = b;
		}

		/**
		 * @param string
		 */
		public void setTargetID(String string) {
			targetID = string;
		}

	}


    //
    // Write
    //


	public String toString(GPGraph graph) {
		userObjectMap.clear();
		cellMap.clear();
		attrs.clear();

		String xml = "\n";

		GraphModel model = graph.getModel();
		xml += "\n";
		xml += outputModel(model, "\t", null);
		xml += "\n";

		xml += "\n";
		xml += outputAttributes("\t");
		xml += "\n";

		xml += "\n";
		xml += encodeUserObjects("\t", userObjectMap);
		xml += "\n";

		xml += "\n";
		xml += outputView(graph, "\t");
		xml += "\n";

		// Close main tags
		xml += "\n";
		return xml;
	}

        public String outputView(GPGraph graph, String indent) {
		String xml = indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n"
		    + indent + "\n";
		return xml;
        }

	public String outputModel(GraphModel model, String indent, Object parent) {
		String xml = new String("");
		int max =
			(parent != null)
				? model.getChildCount(parent)
				: model.getRootCount();
		for (int i = 0; i < max; i++) {
			Object cell =
				(parent != null)
					? model.getChild(parent, i)
					: model.getRootAt(i);
			if (cell != null)
				xml += outputCell(indent, model, cell);
		}
		return xml;
	}

	public String outputCell(String indent, GraphModel model, Object cell) {
		Map map = new Hashtable(model.getAttributes(cell));
		Rectangle r = (Rectangle) map.remove(GraphConstants.BOUNDS);
		Object value = map.remove(GraphConstants.VALUE);
		if (GraphConstants.getFont(map).equals(GraphConstants.defaultFont))
			map.remove(GraphConstants.FONT);
		Object source = model.getSource(cell);
		Object target = model.getTarget(cell);
		if (GraphConstants.getRouting(map) != null)
		    map.remove(GraphConstants.POINTS);
		String sourceID = "";
		String targetID = "";
		if (source != null)
			sourceID = " src=\"" + getID(source) + "\"";
		if (source != null)
			targetID = " tgt=\"" + getID(target) + "\"";
		String bounds = "";
		String valueS = "";
		if (r != null && !model.isEdge(cell) && !model.isPort(cell) && !r.equals(DefaultGraphCell.defaultBounds))
			bounds = " rect=\"" + encodeValue(r) + "\"";
		List p = GraphConstants.getPoints(map);
		map.remove(GraphConstants.POINTS);
		String points = "";
		if (p != null && !p.equals(DefaultEdge.defaultPoints)) {
			String tmp = encodeValue(p);
			if (tmp.length() > 0)
			    points = " pts=\"" + tmp + "\"";
		}
		if (value != null)
			valueS = " val=\"" + getUserObjectID(value) + "\"";
		String attrID = "";
		if (map.size() > 0)
			attrID = " attr=\"" + attrCol.addMap(map) + "\"";
		String xml =
			new String(
				indent
					+ " 0)
			xml += ">\n"
				+ outputModel(model, indent + "\t", cell)
				+ indent
				+ "\n";
		else
			xml += "/>\n";
		return xml;
	}

	public int getUserObjectID(Object object) {
		Integer index = (Integer) userObjectMap.get(object);
		if (index != null)
			return index.intValue();
		index = new Integer(userObjectMap.size() + 1);
		userObjectMap.put(object, index);
		return index.intValue();
	}

	public int getID(Object object) {
		Integer index = (Integer) cellMap.get(object);
		if (index != null)
			return index.intValue();
		index = new Integer(cellMap.size() + 1);
		cellMap.put(object, index);
		return index.intValue();
	}

	public String outputAttributes(String indent) {
		Set set = new HashSet();
		set.add(PARENT);
		set.add(GraphConstants.BOUNDS);
		set.add(GraphConstants.POINTS);

		String xml = new String();
		for (int i = 0; i < attrCol.maps.size(); i++) {
			Map map = (Map) attrCol.maps.get(i);
			Object hook = map.get(PARENT);
			String hookS = "";
			if (hook != null)
				hookS = " pid=\"" + attrCol.maps.indexOf(hook) + "\"";
			xml += indent + "\n";
			xml += encodeMap(indent + "\t", map, false, set, false);
			xml += indent + "\n";
		}
		return xml;
	}

	public class AttributeCollection {

		public List maps = new LinkedList();

		public int addMap(Map attr) {
			Iterator it = maps.iterator();
			Map storeMap = new Hashtable(attr);
			Map hook = storeMap;
			while (it.hasNext()) {
				Map ref = (Map) it.next();
				Map diff = diffMap(ref, attr);
				if (diff.size() < storeMap.size()) {
					hook = ref;
					storeMap = diff;
				}
			}
			if (storeMap.size() == 0 && hook != storeMap)
				return maps.indexOf(hook);
			if (hook != storeMap)
				storeMap.put(PARENT, hook);
			maps.add(storeMap);
			return maps.indexOf(storeMap);
		}

		public void clear() {
			maps.clear();
		}

		/**
		 * Returns a new map that contains all (key, value)-pairs
		 * of newState where either key is not used
		 * or value is different for key in oldState.
		 * In other words, this method removes the common entries
		 * from oldState and newState, and returns the "difference"
		 * between the two.
		 *
		 * This method never returns null.
		 */
		public Map diffMap(Map oldState, Map newState) {
			// Augment oldState
			Stack s = new Stack();
			s.add(oldState);
			Object hook = oldState.get(PARENT);
			while (hook instanceof Map) {
				s.add(hook);
				hook = ((Map) hook).get(PARENT);
			}
			oldState = new Hashtable();
			while (!s.isEmpty()) {
				oldState.putAll((Map) s.pop());
			}
			Map diff = new Hashtable();
			Iterator it = newState.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry entry = (Map.Entry) it.next();
				Object key = entry.getKey();
				Object oldValue = oldState.remove(key);
				if (key != PARENT) {
					Object newValue = entry.getValue();
					if (oldValue == null || !oldValue.equals(newValue))
						diff.put(key, newValue);
				}
			}
			it = oldState.keySet().iterator();
			while (it.hasNext()) {
				Object key = it.next();
				if (!oldState.get(key).equals(""))
					diff.put(key, "");
			}
			diff.remove(PARENT);
			return diff;
		}

	}


    //
    // Codec
    //

	public static String[] knownKeys =
		new String[] {
			GraphConstants.ABSOLUTE,
			GraphConstants.AUTOSIZE,
			GraphConstants.BACKGROUND,
			GraphConstants.BEGINFILL,
			GraphConstants.BEGINSIZE,
			GraphConstants.BENDABLE,
			GraphConstants.BORDER,
			GraphConstants.BORDERCOLOR,
			GraphConstants.BOUNDS,
			GraphConstants.CONNECTABLE,
			GraphConstants.DASHPATTERN,
			GraphConstants.DISCONNECTABLE,
			GraphConstants.EDITABLE,
			GraphConstants.ENDFILL,
			GraphConstants.ENDSIZE,
			GraphConstants.FONT,
			GraphConstants.FOREGROUND,
			GraphConstants.HORIZONTAL_ALIGNMENT,
			GraphConstants.VERTICAL_ALIGNMENT,
			GraphConstants.ICON,
			GraphConstants.LABELPOSITION,
			GraphConstants.LINEBEGIN,
			GraphConstants.LINECOLOR,
			GraphConstants.LINEEND,
			GraphConstants.LINESTYLE,
			GraphConstants.LINEWIDTH,
			GraphConstants.MOVEABLE,
			GraphConstants.OFFSET,
			GraphConstants.OPAQUE,
			GraphConstants.POINTS,
			GraphConstants.ROUTING,
			GraphConstants.SIZE,
			GraphConstants.SIZEABLE,
			GraphConstants.VALUE };

	public static Class[] keyTypes =
		new Class[] {
			Boolean.class,
			Boolean.class,
			Color.class,
			Boolean.class,
			Integer.class,
			Boolean.class,
			Border.class,
			Color.class,
			Rectangle.class,
			Boolean.class,
			float[].class,
			Boolean.class,
			Boolean.class,
			Boolean.class,
			Integer.class,
			Font.class,
			Color.class,
			Integer.class,
			Integer.class,
			Icon.class,
			Point.class,
			Integer.class,
			Color.class,
			Integer.class,
			Integer.class,
			Float.class,
			Boolean.class,
			Point.class,
			Boolean.class,
			List.class,
			Edge.Routing.class,
			Dimension.class,
			Boolean.class,
			Object.class };

	public static String encodeMap(
		String indent,
		Map attributes,
		boolean invert,
		Set excludeAttributes,
		boolean URLencodeValues) {
		String xml = new String("");
		Iterator it = attributes.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			Object key = entry.getKey();
			if (excludeAttributes == null
				|| !excludeAttributes.contains(key)) {
				Object value = entry.getValue();
				if (invert) {
					Object tmp = key;
					key = value;
					value = tmp;
				}
				if (URLencodeValues) {
				    try {
					key = URLEncoder.encode(key.toString(), "UTF-8");
					value = URLEncoder.encode(encodeValue(value), "UTF-8");
				    } catch (Exception e) {
					System.err.println(e.getMessage());
				    }
				}
				xml += indent
					+ "\n";
			}
		}
		return xml;
	}

	public static String encodeUserObjects(
		String indent,
		Map userObjects) {
		String xml = new String("");
		Iterator it = userObjects.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			Object key = entry.getValue();
			Object value = entry.getKey();
			if (value instanceof GPUserObject)
			{
			    xml += indent
				+ "\n";
			}
			else if ( value instanceof JGpdModelNode )
			{
			    xml += indent
				    + "\n";

			    String local_indent = indent + "\t";
			    // Output the entire XML representation of this object
			    xml += ((JGpdModelNode) value).writeXML(local_indent + "  ");

			    xml += indent
			        + "\n";
			}
			else
			{
			    try {
				value = URLEncoder.encode(encodeValue(value), "UTF-8");
			    } catch (Exception e) {
				System.err.println(e.getMessage());
			    }
			    xml += indent
				+ "\n";
			}
		}
		return xml;
	}

	public static String encodeKey(String key) {
// 		for (int i = 0; i < knownKeys.length; i++)
// 			if (key.equals(knownKeys[i]))
// 				return Integer.toString(i);
		return key;
	}

	public static String encodeValue(Object value) {
	    String ret = "";
		if (value instanceof Rectangle) {
			Rectangle r = (Rectangle) value;
			ret =  r.x + "," + r.y + "," + r.width + "," + r.height;
		} else if (value instanceof List) { // TODO: non-points
			List list = (List) value;
			String s = "";
			for (int i = 0; i < list.size(); i++) {
				if (list.get(i) instanceof Point) {
					Point pt = (Point) list.get(i);
					s = s + pt.x + "," + pt.y + ",";
				}
			}
			ret =  (s.length() > 0) ? s.substring(0, s.length() - 1) : s;
		} else if (value instanceof Font) {
			Font font = (Font) value;
			ret =  font.getName()
				+ ","
				+ font.getSize()
				+ ","
				+ font.getStyle();
		} else if (value instanceof Color) {
			Color color = (Color) value;
			ret =  Integer.toString(color.getRed())
				+ ","
				+ Integer.toString(color.getGreen())
				+ ","
				+ Integer.toString(color.getBlue());
		} else if (value instanceof Point) {
			Point point = (Point) value;
			ret =  point.x + "," + point.y;
		} else if (value instanceof float[]) {
			float[] f = (float[]) value;
			String s = "";
			for (int i = 0; i < f.length; i++) {
				s = s + Float.toString(f[i]) + ",";
			}
			ret =  s.substring(0, s.length() - 1);
		} else if (value instanceof Border) {
			if (value instanceof LineBorder) {
				LineBorder lb = (LineBorder) value;
				ret =  "L,"
					+ lb.getLineColor().getRGB()
					+ ","
					+ lb.getThickness();
			} else if (value instanceof BevelBorder) {
				BevelBorder bb = (BevelBorder) value;
				ret =  "B," + bb.getBevelType();
			}
		} else if (value instanceof ImageIconBean) {
			ImageIconBean icon = (ImageIconBean) value;
			ret =  icon.getFileName();
		} else if (value instanceof Edge.Routing) {
		    if (value instanceof DefaultEdge.DefaultRouting)
			ret =  "simple";
		} else if (value != null)
		    ret =  value.toString();
		return ret;
	}

	public static Map decodeMap(Node node, boolean useKnownKeys, boolean URLdecodeValues) {
		Hashtable map = new Hashtable();
		for (int i = 0; i < node.getChildNodes().getLength(); i++) {
			Node child = node.getChildNodes().item(i);
			if (child.getNodeName().toLowerCase().equals("a")) {
				Node key = child.getAttributes().getNamedItem("key");
				Node value = child.getAttributes().getNamedItem("val");
				if (key != null && value != null) {
					String keyVal = key.getNodeValue().toString();
					Object valueS = value.getNodeValue().toString();
					if (useKnownKeys) {
					    int index = -1;
					    for (int j=0; j




© 2015 - 2025 Weber Informatics LLC | Privacy Policy