1   /***
2    * Aggregator.java
3    * 
4    * Project: Dependency Tool
5    * 
6    * WHEN           WHO           WHAT
7    * 06.06.2003     pko           initial public release
8    * 10.12.2002     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.Enumeration;
33  
34  import java.util.regex.PatternSyntaxException;
35  import java.util.regex.Pattern;
36  import java.util.regex.Matcher;
37  
38  import org.apache.log4j.Logger;
39  
40  import att.grappa.*;
41  
42  /***
43   * This class is responsible for aggregating nodes in a graph
44   * accordingly to a regexp.
45   *
46   * @author Pawel Kowalski
47   * @version 1.0-beta
48   */
49  public class Aggregator extends AbstractGraphProcessor {
50      
51      /***
52       * Log4j Logger.
53       */
54      private static final Logger LOG = Logger.getLogger(Aggregator.class);
55  
56      /***
57       * A <code>regexp String</code> associated with this
58       * <code>Aggregator</code>.
59       */
60      protected String m_regexpString = null;
61  
62      /***
63       * A precompiled regexp matcher.
64       */
65      protected Pattern m_regexp = null;
66  
67      /***
68       * A flag, telling whether the specified regular expression could
69       * be successfully used for building a <code>RE</code> Program.
70       */
71      protected boolean m_noRegexp = false;
72  
73      /***
74       * Creates a new <code>Aggregator</code> instance.
75       */
76      public Aggregator() {
77      }
78  
79      /***
80       * Creates a new <code>Aggregator</code> with a name and a String
81       * used to be used for building a RE (regular expression program).
82       *
83       * @param name a <code>String</code> value
84       * @param regexpString a <code>String</code> value
85       */
86      public Aggregator(String name, String regexpString) {
87          super(name);
88          setRegexp(regexpString);
89      }
90  
91      /***
92       * Set a regular expression for aggregating nodes.
93       *
94       * @param regexpString a <code>String</code> value
95       */
96      public void setRegexp(String regexpString) {
97          m_regexpString = regexpString;
98          try {
99              m_regexp = Pattern.compile(regexpString);
100         } catch (PatternSyntaxException e) {
101             LOG.error("Syntax error in regexp: " + regexpString);
102             m_noRegexp = true;
103         }
104     }
105 
106     /***
107      * Get the regexp used to aggregate nodes.
108      *
109      * @return a <code>String</code> value
110      */
111     public String getRegexp() {
112         return m_regexpString;
113     }
114 
115     /***
116      * Returns the Pattern (Regexp) used by this Aggregator.
117      *
118      * @return a <code>Pattern</code> value
119      */
120     public Pattern getPattern() {
121         return m_regexp;
122     }
123 
124     /***
125      * Aggregate nodes accordingl to a regexp. The aggregate node
126      * will have the name associated with this class. This is an
127      * Implementation of the abstract method inherited from the
128      * <code>AbstractGraphProcessor</code>.
129      *
130      * @param graph a <code>Graph</code> value
131      * @return a <code>Graph</code> value
132      */
133     public Graph process(Graph graph) {
134 
135         // syntax error in regexp, ignore this aggregation
136         //
137         if (m_noRegexp) {
138             return graph;
139         }
140 
141         LOG.debug("Process graph: " + graph.getName());
142 
143         Node node = null;
144         String nodeName = "";
145         Node newNode = null;
146         Node tailNode = null;
147         Node headNode = null;
148         Edge edge = null;
149         Edge newEdge = null;
150         
151         // enumerate over all nodes
152         //
153         for (Enumeration enum = graph.nodeElements(); enum.hasMoreElements(); ) {
154             node = (Node)enum.nextElement();
155             nodeName = node.getName();
156 
157             // does the node match the regexp
158             //
159             Matcher matcher = m_regexp.matcher(nodeName);
160             if (matcher.matches() && !nodeName.equals(m_name)) {
161 
162                 // create new aggregate node, or reuse an existing one
163                 //                   
164                 if (newNode == null) {
165                     if ((newNode = graph.findNodeByName(m_name)) == null) {
166                         newNode = new Node(graph, m_name);
167                     }
168                     newNode.setAttribute(GrappaConstants.STYLE_ATTR, "filled");
169                     newNode.setAttribute(GrappaConstants.COLOR_ATTR, "powderblue");                    
170                 }
171 
172                 // process in-edges
173                 //
174                 for (Enumeration inEnum = node.inEdgeElements(); inEnum.hasMoreElements(); ) {
175                     edge = (Edge)inEnum.nextElement();
176 
177                     // no multiple edges
178                     //
179                     if (!(Edge.findEdgesByEnds(newNode, edge.getTail()).hasMoreElements())) {
180 
181                         // no edges showing on self
182                         //
183                         if (!(edge.getTail() == newNode)) {
184                             newEdge = new Edge(graph, edge.getTail(), newNode);
185                         }
186                     }
187 
188                     tailNode = edge.getTail();
189 
190                     // remove edge from graph and head/tail nodes
191                     //
192                     node.removeEdge(edge, true);
193                     tailNode.removeEdge(edge, false);
194                     graph.removeEdge(edge.getName());
195                 }
196 
197                 // process out-edges
198                 //
199                 for (Enumeration outEnum = node.outEdgeElements(); outEnum.hasMoreElements(); ) {
200                     edge = (Edge)outEnum.nextElement();
201 
202                     // no multiple edges
203                     //
204                     if (!(Edge.findEdgesByEnds(edge.getHead(), newNode).hasMoreElements())) {
205 
206                         // no edges showing on self
207                         //
208                         if (!(edge.getHead() == newNode)) {
209                             newEdge = new Edge(graph, newNode, edge.getHead());
210                         }
211                     }
212 
213                     headNode = edge.getHead();
214 
215                     // remove edge from graph and head/tail nodes
216                     //
217                     node.removeEdge(edge, false);
218                     headNode.removeEdge(edge, true);
219                     graph.removeEdge(edge.getName());
220                 }
221 
222                 // remove node
223                 //
224                 graph.removeNode(nodeName);
225                 LOG.debug("Removed node: " + nodeName);                     
226             }
227         }
228         return graph;
229     }
230 }
This page was automatically generated by Maven