gt: 				GraphNode node = viewer.getGraphModelNode(key);
context: /*******************************************************************************
   * Copyright 2005, 2009, CHISEL Group, University of Victoria, Victoria, BC,
   * Canada. All rights reserved. This program and the accompanying materials are
   * made available under the terms of the Eclipse Public License v1.0 which
   * accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   * 
   * Contributors: The Chisel Group, University of Victoria
   ******************************************************************************/
  package org.eclipse.zest.core.viewers.internal;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  
  import org.eclipse.draw2d.IFigure;
  import org.eclipse.jface.viewers.IBaseLabelProvider;
  import org.eclipse.jface.viewers.IStructuredContentProvider;
  import org.eclipse.jface.viewers.StructuredViewer;
  import org.eclipse.jface.viewers.ViewerFilter;
  import org.eclipse.swt.SWT;
  import org.eclipse.zest.core.viewers.IFigureProvider;
  import org.eclipse.zest.core.viewers.INestedContentProvider;
  import org.eclipse.zest.core.widgets.Graph;
  import org.eclipse.zest.core.widgets.GraphConnection;
  import org.eclipse.zest.core.widgets.GraphItem;
  import org.eclipse.zest.core.widgets.GraphNode;
  import org.eclipse.zest.core.widgets.IContainer;
  
  /*
   * Base class that can be used for model factories. Offers facilities to style
   * the items that have been created by the factory.
   * 
   * @author Del Myers
   */
  // @tag zest.bug.160367-Refreshing.fix : update the factory to use the
  // IStylingGraphModelFactory
  public abstract class AbstractStylingModelFactory implements IStylingGraphModelFactory {
  	private AbstractStructuredGraphViewer viewer;
  	private int connectionStyle;
  	private int nodeStyle;
  	private List /* ConstraintAdapater */constraintAdapters = new ArrayList();
  	private HashMap nodesLocationMap = new HashMap();
  
  	/**
  	 * 
  	 */
  	public AbstractStylingModelFactory(AbstractStructuredGraphViewer viewer) {
  		this.viewer = viewer;
  		this.connectionStyle = SWT.NONE;
  		this.nodeStyle = SWT.NONE;
  		if (viewer instanceof AbstractStructuredGraphViewer) {
  			this.constraintAdapters = (viewer).getConstraintAdapters();
  		}
  	}
  
  	public void styleConnection(GraphConnection conn) {
  		// recount the source and target connections on the node.
  		// this isn't a great way to do it, because it results in
  		// an n^2 algorithm. But, if anyone can figure out a better way
  		// go ahead and try it.
  		GraphNode source = conn.getSource();
  		GraphNode dest = conn.getDestination();
  		LinkedList rightList = getConnectionList(source, dest);
  
  		LinkedList leftList = null;
  
  		if (dest != source) {
  			leftList = getConnectionList(dest, source);
  		}
  
  		// adjust the arcs going from source to destination
  		adjustCurves(rightList);
  		// adjust the arcs going from destination to source
  		if (leftList != null) {
  			adjustCurves(leftList);
  		}
  	}
  
  	/**
  	 * Takes a list of IGraphModelConnections and adjusts the curve depths and
  	 * the bezier curves based on the number of curves in the list.
  	 * 
  	 * @param rightList
  	 */
  	protected void adjustCurves(List connections) {
  		// @tag TODO curves : add back this code to adjust the curves
  		//		int scale = 3;
  		//		for (int i = 0; i < connections.size(); i++) {
  		//			GraphConnection conn = (GraphConnection) connections.get(i);
  		//			if (conn.getSource() == conn.getDestination()) {
  		//				scale = 5;
  		//			}
  		//			// even if the connection isn't curved in the style, the edit part
  		//			// may decide that it should be curved if source and dest are equal.
  		//			// @tag drawing(arcs) : check here if arcs are too close when being
  		//			// drawn. Adjust the constant.
  		//			int lineWidth = conn.getLineWidth();
  		//			conn.setCurveDepth((i + 1) * (scale + lineWidth));
  		//
  		//			// @tag zest(bug(152530-Bezier(fix))) : set the angles, etc based on
  		//			// the count.
  		//			// limit the angle to 90 degrees.
  		//			conn.setStartAngle(90.0 - 85.0 / Math.pow(i, 1.0 / 9.0));
  		//			conn.setEndAngle(85.0 / Math.pow(i, 1.0 / 9.0) - 90.0);
  		//			// limit the length to 1
  		//			conn.setStartLength(.75 - .25 / (Math.sqrt(i)));
  		//			conn.setEndLength(.75 - .25 / (Math.sqrt(i)));
  		//		}
  	}
  
  	/**
  	 * @param source
  	 * @param dest
  	 * @return
  	 */
  	private LinkedList getConnectionList(GraphNode source, GraphNode dest) {
  		LinkedList list = new LinkedList();
  		Iterator i = source.getSourceConnections().iterator();
  		while (i.hasNext()) {
  			GraphConnection c = (GraphConnection) i.next();
  			if (c.getDestination() == dest) {
  				list.add(c);
  			}
  		}
  		return list;
  	}
  
  	public void styleItem(GraphItem item) {
  		GraphItemStyler.styleItem(item, getLabelProvider());
  		if (item instanceof GraphConnection) {
  			styleConnection((GraphConnection) item);
  		}
  	}
  
  	public StructuredViewer getViewer() {
  		return viewer;
  	}
  
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see org.eclipse.zest.core.internal.graphmodel.IStylingGraphModelFactory#getLabelProvider()
  	 */
  	public IBaseLabelProvider getLabelProvider() {
  		return viewer.getLabelProvider();
  	}
  
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see org.eclipse.zest.core.internal.graphmodel.IStylingGraphModelFactory#getContentProvider()
  	 */
  	public IStructuredContentProvider getContentProvider() {
  		return (IStructuredContentProvider) viewer.getContentProvider();
  	}
  
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see org.eclipse.zest.core.internal.graphmodel.IStylingGraphModelFactory#createConnection(org.eclipse.zest.core.internal.graphmodel.GraphModel,
  	 *      java.lang.Object, java.lang.Object, java.lang.Object)
  	 */
  	public GraphConnection createConnection(Graph graph, Object element, Object source, Object dest) {
  		if (source == null || dest == null) {
  			return null;
  		}
  		GraphConnection oldConnection = viewer.getGraphModelConnection(element);
  		GraphNode sn = viewer.getGraphModelNode(source);
  		GraphNode dn = viewer.getGraphModelNode(dest);
  		if (oldConnection != null) {
  			if (sn != oldConnection.getSource() || dn != oldConnection.getDestination()) {
  				viewer.removeGraphModelConnection(oldConnection);
  			} else {
  				styleItem(oldConnection);
  				return oldConnection;
  			}
  		}
  		IFigureProvider figureProvider = null;
  		if (getLabelProvider() instanceof IFigureProvider) {
  			figureProvider = (IFigureProvider) getLabelProvider();
  		}
  		if (sn == null) {
  			IFigure figure = null;
  			if (figureProvider != null) {
  				figure = figureProvider.getFigure(source);
  			}
  			if (figure != null) {
  				sn = createNode(graph, source, figure);
  			} else {
  				sn = createNode(graph, source);
  			}
  		}
  		if (dn == null) {
  			IFigure figure = null;
  			if (figureProvider != null) {
  				figure = figureProvider.getFigure(source);
  			}
  			if (figure != null) {
  				dn = createNode(graph, dest, figure);
  			} else {
  				dn = createNode(graph, dest);
  			}
  		}
  		GraphConnection c = viewer.addGraphModelConnection(element, sn, dn);
  		styleItem(c);
  		return c;
  	}
  
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see org.eclipse.zest.core.internal.graphmodel.IStylingGraphModelFactory#createNode(org.eclipse.zest.core.internal.graphmodel.GraphModel,
  	 *      java.lang.Object)
  	 */
  	public GraphNode createNode(Graph graph, Object element, IFigure figure) {
  		GraphNode node = null;
  		if (getContentProvider() instanceof INestedContentProvider) {
  			boolean isContainer = ((INestedContentProvider) getContentProvider()).hasChildren(element);
  			if (isContainer) {
  				node = viewer.addGraphModelContainer(element);
  				styleItem(node);
  				Object[] childNodes = ((INestedContentProvider) getContentProvider()).getChildren(element);
  				childNodes = filter(getViewer().getInput(), childNodes);
  				if (childNodes == null) {
  					return node;
  				}
  				for (int i = 0; i < childNodes.length; i++) {
  					GraphNode childNode = viewer.addGraphModelNode((IContainer) node, childNodes[i]);
  					styleItem(childNode);
  				}
  				((IContainer) node).applyLayout();
  				return node;
  			}
  		}
  		node = viewer.addGraphModelNode(element, figure);
  		styleItem(node);
  		return node;
  	}
  
  	public GraphNode createNode(Graph graph, Object element) {
  		IFigure nodeFigure = null;
  		if (getLabelProvider() instanceof IFigureProvider) {
  			nodeFigure = ((IFigureProvider) getLabelProvider()).getFigure(element);
  		}
  		return this.createNode(graph, element, nodeFigure);
  	}
  
  	public void setConnectionStyle(int style) {
  		this.connectionStyle = style;
  	}
  
  	/**
  	 * @return the connectionStyle
  	 */
  	public int getConnectionStyle() {
  		return connectionStyle;
  	}
  
  	public void setNodeStyle(int style) {
  		this.nodeStyle = style;
  	}
  
  	public List /* ConstraintAdapter */getConstraintAdapters() {
  		return this.constraintAdapters;
  	}
  
  	/**
  	 * @return the nodeStyle
  	 */
  	public int getNodeStyle() {
  		return nodeStyle;
  	}
  
  	/**
  	 * Default implementation simply restyles the item, regardless of the
  	 * properties.
  	 */
  	public void update(GraphItem item) {
  		styleItem(item);
  	}
  
  	/**
  	 * Default implementation simply restyles the items, regardless of the
  	 * properties.
  	 */
  	public void update(GraphItem[] items) {
  		for (int i = 0; i < items.length; i++) {
  			styleItem(items[i]);
  		}
  	}
  
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see org.eclipse.zest.core.internal.graphmodel.IStylingGraphModelFactory#refreshGraph(org.eclipse.zest.core.internal.graphmodel.GraphModel)
  	 */
  	public void refreshGraph(Graph graph) {
  		// with this kind of graph, it is just as easy and cost-effective to
  		// rebuild the whole thing.
  
  		Map oldMap = viewer.getNodesMap();
  //		HashMap nodesMap = new HashMap();
  		// have to copy the Map data accross so that it doesn't get overwritten
  		for (Iterator keys = oldMap.keySet().iterator(); keys.hasNext();) {
  			Object key = keys.next();
  			nodesLocationMap.put(key, oldMap.get(key));
  		}
  		clearGraph(graph);
  		doBuildGraph(graph);
  		// update the positions on the new nodes to match the old ones.
  		GraphNode[] nodes = getNodesArray(graph);
  		// save a little time, go with the smallest list as the primary list
  		if (nodes.length < nodesLocationMap.keySet().size()) {
  			for (int i = 0; i < nodes.length; i++) {
  				GraphNode oldNode = (GraphNode) nodesLocationMap.get(nodes[i].getData());
  				if (oldNode != null) {
  					nodes[i].setLocation(oldNode.getLocation().x, oldNode.getLocation().y);
  					if (oldNode.isSizeFixed()) {
  						nodes[i].setSize(oldNode.getSize().width, oldNode.getSize().height);
  					}
  				}
  			}
  		} else {
  			for (Iterator i = nodesLocationMap.keySet().iterator(); i.hasNext();) {
  				Object key = i.next();
  