001: /*
002: * Hammurapi
003: * Automated Java code review system.
004: * Copyright (C) 2004 Johannes Bellert
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.com
021: * e-Mail: Johannes.Bellert@ercgroup.com
022: *
023: * * Created on Apr 11, 2004
024: *
025: */
026: package org.hammurapi.inspectors.metrics;
027:
028: import java.util.Enumeration;
029: import java.util.Hashtable;
030:
031: import org.w3c.dom.Document;
032: import org.w3c.dom.Element;
033:
034: import com.pavelvlasov.jsel.Parameter;
035: import com.pavelvlasov.jsel.Type;
036: import com.pavelvlasov.jsel.TypeBody;
037: import com.pavelvlasov.jsel.TypeDefinition;
038: import com.pavelvlasov.jsel.TypeSpecification;
039: import com.pavelvlasov.jsel.VariableDefinition;
040: import com.pavelvlasov.jsel.impl.ClassImpl;
041: import com.pavelvlasov.jsel.impl.ClassTypeSpecificationImpl;
042:
043: /**
044: * @author mucbj0
045: *
046: * JDepend
047: *
048: * Afferent Couplings (Ca)
049: * The number of other packages that depend upon classes within the package
050: * is an indicator of the package's responsibility.
051: *
052: * Efferent Couplings (Ce)
053: * The number of other packages that the classes in the package depend upon
054: * is an indicator of the package's independence.
055: *
056: **/
057: public class Coupling {
058:
059: public Hashtable classCouplingMetric = new Hashtable();
060: public Hashtable packageCouplingMetric = new Hashtable();
061: public Hashtable allClasses = null;
062: public Hashtable allMethodsImplemented = new Hashtable();
063: public Hashtable allMethodsInvoked = new Hashtable();
064:
065: public Hashtable allVariables = new Hashtable();
066:
067: //!! tbd: Set an meaningful name to the CouplingMetricOfPackage or use a different class
068: private CouplingMetricOfPackage totalCouplingMetricOfProject = new CouplingMetricOfPackage(
069: "Project");
070:
071: /* public Coupling(ClassMap _classes, File _projectBaseDir){
072: super();
073: allClasses = _classes;
074: projectBaseDir = _projectBaseDir;
075: }
076:
077: public void init(){
078: logger.debug( "-> init " );
079: Enumeration enum = allClasses.elements();
080: while (enum.hasMoreElements()){
081: Type c =(Type)enum.nextElement();
082: logger.debug( "Class " + c.toKey() );
083: CouplingMetricOfClass cmc = new CouplingMetricOfClass(c);
084: this.classCouplingMetric.put( c.toKey(), cmc);
085: }
086: // logger.debug( "this.couplingMetric " + this.couplingMetric );
087: logger.debug( "<- init " );
088: return;
089: };
090: */
091:
092: //-------------------------------------------------------------------------
093: public void incrementVariableCoupling(Parameter parameter) {
094:
095: try {
096: if (parameter.getTypeSpecification() instanceof ClassTypeSpecificationImpl) {
097: TypeSpecification ts = parameter.getTypeSpecification();
098: CouplingMetricOfClass cmcParent = (CouplingMetricOfClass) classCouplingMetric
099: .get(parameter.getParent().getEnclosingType()
100: .getFcn());
101: CouplingMetricOfClass cmcVar = (CouplingMetricOfClass) classCouplingMetric
102: .get(ts.getName());
103: if (cmcVar == null) {
104: classCouplingMetric.put(ts.getName(),
105: new CouplingMetricOfClass(ts));
106: } else {
107: cmcVar.afferentVariableCounter++;
108: }
109: if (cmcParent == null) {
110: classCouplingMetric.put(parameter.getParent()
111: .getEnclosingType().getFcn(),
112: new CouplingMetricOfClass(parameter
113: .getParent().getEnclosingType()));
114: } else {
115: cmcParent.efferentVariableCounter++;
116: }
117: // System.out.println( cmcVar );
118: // System.out.println( cmcParent );
119: }
120:
121: } catch (Exception e) {
122: // TODO Auto-generated catch block
123: e.printStackTrace();
124: }
125:
126: }
127:
128: public String determineKey(VariableDefinition var) {
129: String str = "<undefined>";
130: if (var != null) {
131: if (var.getParent() instanceof ClassImpl) {
132: return ((ClassImpl) var.getParent()).getFcn();
133: } else {
134: // System.out.println( ((ClassImpl)var.getCompilationUnit().getTypes().get(0)).getFcn() );
135: }
136: }
137:
138: return str;
139: }
140:
141: public void incrementVariableCoupling(VariableDefinition var) {
142: try {
143: // System.out.println( ">> " + var.getTypeSpecification().getName() );
144: // System.out.println( ">> " + var.getParent().getEnclosingType().getFcn());
145: if (var != null) {
146:
147: String key = determineKey(var);
148: CouplingMetricOfClass cmcParent = (CouplingMetricOfClass) classCouplingMetric
149: .get(key);
150: CouplingMetricOfClass cmcVar = (CouplingMetricOfClass) classCouplingMetric
151: .get(var.getTypeSpecification().getName());
152: if (cmcVar == null) {
153: classCouplingMetric.put(var.getTypeSpecification()
154: .getName(), new CouplingMetricOfClass(var
155: .getTypeSpecification()));
156: } else {
157: cmcVar.afferentVariableCounter++;
158: }
159: if (cmcParent == null) {
160: TypeBody parentEnclosingType = var.getParent()
161: .getEnclosingType();
162: if (parentEnclosingType != null) {
163: classCouplingMetric.put(parentEnclosingType
164: .getFcn(), new CouplingMetricOfClass(
165: parentEnclosingType));
166: }
167: } else {
168: cmcParent.efferentVariableCounter++;
169: }
170: // System.out.println( cmcVar );
171: // System.out.println( cmcParent );
172: }
173:
174: } catch (Exception e) {
175: // TODO Auto-generated catch block
176: e.printStackTrace();
177: }
178:
179: }
180:
181: //-------------------------------------------------------------------------
182:
183: public void doIt() {
184: // init();
185:
186: Enumeration classEnum = allClasses.elements();
187: while (classEnum.hasMoreElements()) {
188: TypeDefinition c = (TypeDefinition) classEnum.nextElement();
189: CouplingMetricOfClass this Cmc = (CouplingMetricOfClass) this .classCouplingMetric
190: .get(c.getFcn());
191:
192: //!! putAll reinitialize allMethodsImplemented !!
193: // allMethodsImplemented.addAll(c.getMethodMap());
194:
195: //determineMethodMetricForClass( c, thisCmc);
196: determineVariableMetricForClass(c, this Cmc);
197:
198: }
199: this .aggregateToPackageMetric();
200: this .findDefects();
201: this .reporting();
202: return;
203: }
204:
205: public void determineVariableMetricForClass(TypeDefinition c,
206: CouplingMetricOfClass this Cmc) {
207: //!! job
208: /*
209: Enumeration enumMet = c.getMethodMap().elements();
210:
211: // -- all local variables
212: while (enumMet.hasMoreElements()) {
213: MethodImplemented mi = (MethodImplemented) enumMet.nextElement();
214:
215: Enumeration enumslvm = mi.getLocalVarMap().elements();
216: while (enumslvm.hasMoreElements()) {
217: Variable v = (Variable) enumslvm.nextElement();
218: assignVariableCountersTo(v, thisCmc);
219: }
220: }
221:
222: Enumeration enumsivm = c.getInstanceVarMap().elements();
223: while (enumsivm.hasMoreElements()) {
224: Variable v = (Variable) enumsivm.nextElement();
225: assignVariableCountersTo(v, thisCmc);
226: }
227: */
228: }
229:
230: public void assignVariableCountersTo(VariableDefinition v,
231: CouplingMetricOfClass this Cmc) {
232: //!!
233: CouplingMetricOfClass cmc = (CouplingMetricOfClass) this .classCouplingMetric
234: .get(v.getName());
235: // lazy intialization
236:
237: if (cmc == null) {
238: // cmc = initializeCouplingMetricOfClassFor(v.getName());
239: }
240:
241: //!! not correcth
242: // cmc.listAfferentTypes.add( (Type)v.getType() );
243: cmc.afferentVariableCounter++;
244: // thisCmc.listEfferentTypes.add(thisCmc.type);
245: this Cmc.efferentVariableCounter++;
246: }
247:
248: public void determineMethodMetricForClass(Type c,
249: CouplingMetricOfClass this Cmc) {
250: /*
251: Enumeration enumMet = c.getMethodMap().elements();
252: while (enumMet.hasMoreElements()) {
253: MethodImplemented mi = (MethodImplemented) enumMet.nextElement();
254: // logger.debug( "\t" +mi.toString() );
255:
256: Enumeration enumMk = mi.getInvokedMethods().elements();
257: while (enumMk.hasMoreElements()) {
258: MethodInvoked mk = (MethodInvoked) enumMk.nextElement();
259: logger.debug("getSignature: " + mk.getSignature());
260: logger.debug("getImplementorType: " + mk.getImplementorType());
261:
262: if (mk.getServiceVariable() != null && mk.getServiceVariable().getType() != null) {
263: logger.debug("getServiceVariable: " + mk.getServiceVariable());
264: logger.debug("mk.getServiceVariable().getType(): " + mk.getServiceVariable().getType());
265:
266: if (mk.getServiceVariable().getType().equals(c)) {
267: thisCmc.reflectiveMethodCounter++;
268: } else {
269: CouplingMetricOfClass cmc =
270: (CouplingMetricOfClass) this.classCouplingMetric.get(mk.getServiceVariable().getType().toKey());
271: // lazy intialization
272:
273: if (cmc == null) {
274: cmc = initializeCouplingMetricOfClassFor(mk.getServiceVariable().getType());
275: }
276: //!! not correct
277: cmc.listAfferentTypes.add(c);
278: cmc.afferentMethodCounter++;
279: thisCmc.listEfferentTypes.add(mk.getServiceVariable().getType());
280: thisCmc.efferentMethodCounter += mk.occurranceCounter;
281:
282: //-- thisCmc is per se in the project scope: no check needed
283: //!! tbd: parameterize root package check
284: if (cmc.type.getRootPackage() != null
285: && cmc.type.getRootPackage().getRootPackageName() != null
286: && (cmc.type.getRootPackage().getRootPackageName().startsWith("com.")
287: || cmc.type.getRootPackage().getRootPackageName().startsWith("org.apache.jsp"))) {
288: cmc.afferentMethodCounterProjectInternal++;
289: thisCmc.efferentMethodCounterProjectInternal += mk.occurranceCounter;
290: }
291:
292: logger.debug("cmc.efferentMethodUnresolvedCounter++ " + cmc.type.getSignature());
293: }
294: } else {
295: logger.debug("thisCmc.efferentMethodUnresolvedCounter++ " + thisCmc.type.getSignature());
296: thisCmc.efferentMethodUnresolvedCounter++;
297: }
298: }
299: }
300: */
301: }
302:
303: public void aggregateToPackageMetric() {
304: /*
305: String rootPack = "";
306: Enumeration enum = classCouplingMetric.elements();
307: while (enum.hasMoreElements()) {
308: CouplingMetricOfClass cCmc =
309: (CouplingMetricOfClass) enum.nextElement();
310: try {
311: if (cCmc.type != null
312: && cCmc.type.getRootPackage() != null
313: && cCmc.type.getRootPackage().getRootPackageName() != null) {
314:
315: rootPack = cCmc.type.getRootPackage().getRootPackageName();
316: }
317: if (rootPack != null && !"".equals(rootPack)) {
318:
319: logger.fatal("rootPack is: " + rootPack);
320: CouplingMetricOfPackage pCmc = (CouplingMetricOfPackage) this.packageCouplingMetric.get(rootPack);
321:
322: // lazy init
323: if (pCmc == null) {
324: logger.debug("Insert Entry: " + rootPack);
325: pCmc = new CouplingMetricOfPackage(rootPack);
326: this.packageCouplingMetric.put(rootPack, pCmc);
327: }
328: pCmc.aggregate(cCmc);
329: this.totalCouplingMetricOfProject.aggregate(pCmc);
330: }
331:
332: } catch (Exception e) {
333: logger.fatal(
334: "Issues in this.packageCouplingMetric.get(cmc.type.getRootPackage());",
335: e);
336: }
337: }
338: */
339: }
340:
341: public void findDefects() {
342: Enumeration metricEnum = classCouplingMetric.elements();
343: while (metricEnum.hasMoreElements()) {
344: CouplingMetricOfClass cmc = (CouplingMetricOfClass) metricEnum
345: .nextElement();
346: // logger.debug(cmc.toXml());
347: }
348: Enumeration enump = packageCouplingMetric.elements();
349: while (enump.hasMoreElements()) {
350: CouplingMetricOfPackage cmc = (CouplingMetricOfPackage) enump
351: .nextElement();
352: }
353:
354: }
355:
356: public CouplingMetricOfClass initializeCouplingMetricOfClassFor(
357: Type c) {
358: /*
359: CouplingMetricOfClass cmc = new CouplingMetricOfClass(c);
360: this.classCouplingMetric.put(c.toKey(), cmc);
361: logger.debug( "<- initializeCouplingMetricOfClassFor");
362: return cmc;
363: */
364: return null;
365: }
366:
367: public void reporting() {
368: /*
369: String extension = ".xml";
370: String dir = ".";
371: File outFile =
372: new File(
373: projectBaseDir,
374: File.separatorChar
375: + "results"
376: + File.separatorChar
377: + "CouplingMetricOfPackage"
378: + extension);
379: try {
380:
381: FileWriter fw = new FileWriter(outFile);
382: fw.write("<Coupling>");
383: fw.write("<ListCouplingMetricOfPackage>");
384: fw.write("<ProjectSummary>");
385: fw.write(this.totalCouplingMetricOfProject.toXml().toString());
386: fw.write("</ProjectSummary>");
387: fw.flush();
388: Enumeration enump = packageCouplingMetric.elements();
389: while (enump.hasMoreElements()) {
390: CouplingMetricOfPackage cmc =
391: (CouplingMetricOfPackage) enump.nextElement();
392: fw.write(cmc.toXml().toString());
393: fw.flush();
394: }
395: fw.write("</ListCouplingMetricOfPackage>");
396:
397: fw.write("<ListCouplingMetricOfClasses>");
398: Enumeration enumc = classCouplingMetric.elements();
399: while (enumc.hasMoreElements()) {
400: CouplingMetricOfClass cmc =
401: (CouplingMetricOfClass) enumc.nextElement();
402:
403: fw.write(cmc.toXml().toString());
404: fw.flush();
405:
406: }
407: fw.write("</ListCouplingMetricOfClasses>");
408: fw.write("</Coupling>");
409: fw.close();
410: } catch (Exception e) {
411: e.printStackTrace();
412: }
413:
414: //
415: // try {
416: // outFile =
417: // new File(
418: // projectBaseDir,
419: // File.separatorChar
420: // + "results"
421: // + File.separatorChar
422: // + "CouplingMetricOfClasses"
423: //
424: // + extension);
425: //
426: // FileWriter fw = new FileWriter(outFile);
427: // fw.write("<ListCouplingMetricOfClasses>");
428: // Enumeration enump = classCouplingMetric.elements();
429: // while (enump.hasMoreElements()) {
430: // CouplingMetricOfClass cmc =
431: // (CouplingMetricOfClass) enump.nextElement();
432: //
433: // fw.write(cmc.toXml().toString());
434: // fw.flush();
435: //
436: // }
437: // fw.write("</ListCouplingMetricOfClasses>");
438: // fw.close();
439: //
440: // } catch (Exception e) {
441: // e.printStackTrace();
442: // }
443: logger.debug("<- reporting ");
444: */
445: }
446:
447: public Element toDom(Document document) {
448:
449: Element root = document.createElement("Coupling");
450: Element ret = document
451: .createElement("ListCouplingMetricOfClasses");
452: root.appendChild(ret);
453:
454: ret.setAttribute("size", String
455: .valueOf(this .classCouplingMetric.size()));
456: Enumeration enumc = this .classCouplingMetric.elements();
457: while (enumc.hasMoreElements()) {
458: CouplingMetricOfClass cmc = (CouplingMetricOfClass) enumc
459: .nextElement();
460: ret.appendChild(cmc.toDom(document));
461: }
462: return ret;
463:
464: }
465:
466: }
|