View Javadoc
1 /*** 2 * LayerOrder.java 3 * 4 * Project: Dependency Tool 5 * 6 * WHEN WHO WHAT 7 * 06.06.2003 pko initial public release 8 * 20.01.2003 pko creation 9 * 10 * Copyright 2003 ELCA Informatique SA 11 * Av. de la Harpe 22-24, 1000 Lausanne 13, Switzerland 12 * www.elca.ch 13 * 14 * This library is free software; you can redistribute it and/or 15 * modify it under the terms of the GNU Lesser General Public License 16 * as published by the Free Software Foundation; either version 2.1 of 17 * the License, or (at your option) any later version. 18 * 19 * This library is distributed in the hope that it will be useful, but 20 * WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 * Lesser General Public License for more details. 23 * 24 * You should have received a copy of the GNU Lesser General Public 25 * License along with this library; if not, write to the Free Software 26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 27 * USA 28 */ 29 30 package ch.elca.dependency.graph; 31 32 import java.util.*; 33 import ch.elca.dependency.adapter.grappa.SubgraphFactory; 34 import ch.elca.dependency.adapter.grappa.NodeFactory; 35 import ch.elca.dependency.adapter.grappa.EdgeFactory; 36 37 import org.apache.log4j.Logger; 38 39 import att.grappa.Graph; 40 import att.grappa.Subgraph; 41 import att.grappa.GrappaConstants; 42 import att.grappa.Node; 43 import att.grappa.Edge; 44 45 /*** 46 * This class represents Layers within a graph. It's creation is based 47 * on the perspectives config. It can be used to layer a graph and 48 * signalize violations of the layering model. 49 * 50 * @author Pawel Kowalski 51 * @version 1.0-beta 52 */ 53 public class LayerOrder extends AbstractGraphProcessor implements LayeringListener { 54 55 /*** 56 * Log4j Logger. 57 */ 58 private static final Logger LOG = Logger.getLogger(LayerOrder.class); 59 60 /*** 61 * Key to store and retrieve the LayerNumber property. 62 */ 63 public static final String LAYER_NUMBER_KEY = "layer-number-key"; 64 65 /*** 66 * A list of all Layers within this Layering. 67 */ 68 private ArrayList m_layers = null; 69 70 /*** 71 * LayeringEventSupport used to delegate tasks associated with LayeringEvents. 72 */ 73 private LayeringEventSupport m_layeringEventSupport = new LayeringEventSupport(); 74 75 /*** 76 * Creates a new <code>LayerOrder</code> instance. 77 * 78 */ 79 public LayerOrder() { 80 this(""); 81 } 82 83 /*** 84 * Creates a new <code>LayerOrder</code> instance. 85 * 86 * @param name a <code>String</code> value 87 */ 88 public LayerOrder(String name) { 89 setName(name); 90 m_layers = new ArrayList(); 91 m_layers.add(0, Layer.UNASSIGNED); 92 addLayeringListener(this); 93 } 94 95 /*** 96 * Add a Layer to this LayerOrder. 97 * 98 * @param layer a <code>Layer</code> value 99 */ 100 public void addLayer(Layer layer) { 101 LOG.debug("Layer added: " + layer.getName()); 102 m_layers.add(1, layer); 103 } 104 105 /*** 106 * Delete all Layers withing this LayerOrder. 107 */ 108 public void resetLayers() { 109 m_layers = new ArrayList(); 110 } 111 112 /*** 113 * Process a graph according to this LayerOrder. This processing 114 * uncovers layering violations. Each time a violation of the 115 * layering is discovered, an instance of this class fires a 116 * LayeringEvent (with the help of LayeringEventSupport). 117 * 118 * @param graph a <code>Graph</code> value 119 * @return a <code>Graph</code> value 120 */ 121 public Graph process(Graph graph) { 122 123 LOG.debug("Processing graph: " + graph.getName()); 124 125 Hashtable mappings = prepareMappings(); 126 Hashtable subgraphs = new Hashtable(); 127 128 Node node = null; 129 Subgraph subgraph = null; 130 String nodeName = null; 131 Layer currentLayer = null; 132 133 for (Iterator iter = m_layers.iterator(); iter.hasNext(); ) { 134 Layer layer = (Layer)iter.next(); 135 if (!subgraphs.containsKey(layer)) { 136 try { 137 subgraph = SubgraphFactory.createNewSubgraph(graph, layer.getName()); 138 subgraph.setAttribute("rank", "same"); 139 ((Hashtable)subgraph.object).put(LAYER_NUMBER_KEY, new Integer(m_layers.indexOf(layer))); 140 subgraphs.put(layer, subgraph); 141 } catch (Exception e){ 142 for (Enumeration enum = graph.subgraphElements(); enum.hasMoreElements(); ) { 143 Subgraph subg = (Subgraph)enum.nextElement(); 144 if (subg.getName().indexOf(layer.getName()) != -1) { 145 subgraphs.put(layer, subg); 146 } 147 } 148 } 149 } 150 } 151 152 for (Enumeration enum = graph.nodeElements(); enum.hasMoreElements(); ) { 153 node = (Node)enum.nextElement(); 154 155 // no layer associated with this node 156 // 157 if ((currentLayer = (Layer)mappings.get(node.getName())) == null) { 158 159 // create an extra "unassigned" subgraph 160 // 161 // if (!subgraphs.containsKey(Layer.UNASSIGNED)) { 162 // subgraph = SubgraphFactory.createNewSubgraph(graph, Layer.UNASSIGNED.getName()); 163 // subgraph.setAttribute("rank", "same"); 164 // ((Hashtable)subgraph.object).put(LAYER_NUMBER_KEY, new Integer(m_layers.indexOf(Layer.UNASSIGNED))); 165 // subgraphs.put(Layer.UNASSIGNED, subgraph); 166 // } 167 168 // assign this node to the UNASSIGNED Layer 169 // 170 subgraph = (Subgraph)subgraphs.get(Layer.UNASSIGNED); 171 node.setSubgraph(subgraph); 172 173 // mark node as unassigned 174 // 175 node.setAttribute(GrappaConstants.STYLE_ATTR, "filled"); 176 node.setAttribute(GrappaConstants.COLOR_ATTR, "coral"); 177 continue; 178 } 179 180 // was a layer-subgraph already created? 181 // 182 // if (!subgraphs.containsKey(currentLayer)) { 183 // subgraph = SubgraphFactory.createNewSubgraph(graph, currentLayer.getName()); 184 // subgraph.setAttribute("rank", "same"); 185 // ((Hashtable)subgraph.object).put(LAYER_NUMBER_KEY, new Integer(m_layers.indexOf(currentLayer))); 186 // subgraphs.put(currentLayer, subgraph); 187 // } 188 189 // assign this node to a layer 190 // 191 subgraph = (Subgraph)subgraphs.get(currentLayer); 192 node.setSubgraph(subgraph); 193 194 LOG.debug("Node: " + node.getName() + " Subgraph: " + subgraph.getName() + " " + String.valueOf(((Hashtable)subgraph.object).get(LAYER_NUMBER_KEY))); 195 } 196 197 // now manipulate the graph, so that it will get 198 // displayed correctly 199 // 200 201 graph.setEdgeAttribute("constraint", "false"); 202 203 // set constraints of all edges to false 204 // 205 Edge forcingEdge = null; 206 for (Enumeration enum = graph.edgeElements(); enum.hasMoreElements(); ) { 207 forcingEdge = (Edge)enum.nextElement(); 208 if (forcingEdge.getHead().getName().indexOf("layer_node") != -1 209 || forcingEdge.getTail().getName().indexOf("layer_node") != -1) { 210 forcingEdge.setAttribute("constraint", "true"); 211 } 212 } 213 214 Layer upperLayer = null; 215 Layer lowerLayer = null; 216 Node upperNode = null; 217 Node lowerNode = null; 218 Subgraph upperSubgraph = null; 219 Subgraph lowerSubgraph = null; 220 221 for (int i = m_layers.size()-1; i >= 0; i--) { 222 223 try { 224 225 // upper 226 // 227 if (i == m_layers.size()-1) { 228 upperLayer = (Layer)m_layers.get(i); 229 upperSubgraph = (Subgraph)subgraphs.get(upperLayer); 230 upperNode = NodeFactory.createLayerNode(upperSubgraph, upperSubgraph.getName()); 231 } else { 232 upperLayer = lowerLayer; 233 upperSubgraph = lowerSubgraph; 234 upperNode = lowerNode; 235 } 236 237 // lower 238 // 239 lowerLayer = (Layer)m_layers.get(i-1); 240 lowerSubgraph = (Subgraph)subgraphs.get(lowerLayer); 241 lowerNode = NodeFactory.createLayerNode(lowerSubgraph, lowerSubgraph.getName()); 242 243 // connecting edge 244 // 245 EdgeFactory.createLayerEdge(graph, upperNode, lowerNode); 246 } catch (Exception e) { 247 // deliberately left empty 248 } 249 } 250 251 // fire an event signalizing a layer violation 252 // 253 Edge edge = null; 254 for (Enumeration enum = graph.edgeElements(); enum.hasMoreElements(); ) { 255 edge = (Edge)enum.nextElement(); 256 257 Integer headLayerInt = ((Integer)((Hashtable)edge.getHead().getSubgraph().object).get(LayerOrder.LAYER_NUMBER_KEY)); 258 Integer tailLayerInt = ((Integer)((Hashtable)edge.getTail().getSubgraph().object).get(LayerOrder.LAYER_NUMBER_KEY)); 259 260 int headLayer = (headLayerInt == null ? 0 : headLayerInt.intValue()); 261 int tailLayer = (tailLayerInt == null ? 0 : tailLayerInt.intValue()); 262 263 if ( headLayer > tailLayer ) { 264 fireLayeringEvent(edge); 265 } 266 } 267 268 return graph; 269 } 270 271 /*** 272 * Prepare package-name (node) to layer (subgraph) mappings and 273 * put them all into a Hashtable. 274 * 275 * @return a <code>Hashtable</code> value 276 */ 277 private Hashtable prepareMappings() { 278 279 Hashtable mappings = new Hashtable(); 280 Layer layer = null; 281 String[] packages = null; 282 283 for (Iterator iter = m_layers.iterator(); iter.hasNext(); ) { 284 285 layer = (Layer)iter.next(); 286 packages = layer.getPackages(); 287 288 for (int i = 0; i < packages.length; i++) { 289 mappings.put(packages[i], layer); 290 } 291 } 292 293 return mappings; 294 } 295 296 /*** 297 * Handle a event fired when a violation of the layering is 298 * discovered. 299 * 300 * @param event a <code>LayeringEvent</code> value 301 */ 302 public void layeringViolated(LayeringEvent event) { 303 Edge edge = event.getEdge(); 304 edge.setAttribute(GrappaConstants.COLOR_ATTR, "crimson"); 305 edge.setAttribute(GrappaConstants.STYLE_ATTR, "lineWidth(3)"); 306 } 307 308 /*** 309 * Add a LayeringListener which will receive LayeringEvents. 310 * 311 * @param listener a <code>LayeringListener</code> value 312 */ 313 public void addLayeringListener(LayeringListener listener) { 314 m_layeringEventSupport.addLayeringListener(listener); 315 } 316 317 /*** 318 * Remove a LayeringListener from the collection of Listeners 319 * receiving LayeringEvents. 320 * 321 * @param listener a <code>LayeringListener</code> value 322 */ 323 public void removeLayeringListener(LayeringListener listener) { 324 m_layeringEventSupport.removeLayeringListener(listener); 325 } 326 327 /*** 328 * Fire a LayeringEvent with the help of a LayeringEventSupport. 329 * 330 * @param edge an <code>Edge</code> value 331 */ 332 private void fireLayeringEvent(Edge edge) { 333 m_layeringEventSupport.fireLayeringEvent(edge); 334 } 335 }

This page was automatically generated by Maven