001: /*
002: * Copyright (c) 2001-2007, Jean Tessier
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * * Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * * Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in the
014: * documentation and/or other materials provided with the distribution.
015: *
016: * * Neither the name of Jean Tessier nor the names of his contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032:
033: package com.jeantessier.metrics;
034:
035: import java.lang.reflect.*;
036: import java.util.*;
037:
038: import org.apache.log4j.*;
039: import org.apache.oro.text.perl.*;
040:
041: public class MetricsFactory {
042: private static final Perl5Util perl = new Perl5Util();
043:
044: private String projectName;
045: private MetricsConfiguration configuration;
046:
047: private Map<String, Metrics> projects = new HashMap<String, Metrics>();
048: private Map<String, Metrics> groups = new HashMap<String, Metrics>();
049: private Map<String, Metrics> classes = new HashMap<String, Metrics>();
050: private Map<String, Metrics> methods = new HashMap<String, Metrics>();
051:
052: private Map<String, Metrics> includedProjects = new HashMap<String, Metrics>();
053: private Map<String, Metrics> includedGroups = new HashMap<String, Metrics>();
054: private Map<String, Metrics> includedClasses = new HashMap<String, Metrics>();
055: private Map<String, Metrics> includedMethods = new HashMap<String, Metrics>();
056:
057: private WordCounter counter = new WordCounter();
058:
059: public MetricsFactory(String projectName,
060: MetricsConfiguration configuration) {
061: this .projectName = projectName;
062: this .configuration = configuration;
063: }
064:
065: public String getProjectName() {
066: return projectName;
067: }
068:
069: public MetricsConfiguration getConfiguration() {
070: return configuration;
071: }
072:
073: public Metrics createProjectMetrics() {
074: return createProjectMetrics(getProjectName());
075: }
076:
077: public Metrics createProjectMetrics(String name) {
078: Metrics result = projects.get(name);
079:
080: if (result == null) {
081: result = buildProjectMetrics(name);
082: projects.put(name, result);
083: }
084:
085: return result;
086: }
087:
088: private Metrics buildProjectMetrics(String name) {
089: Metrics result = new Metrics(name);
090:
091: populateMetrics(result, getConfiguration()
092: .getProjectMeasurements());
093:
094: return result;
095: }
096:
097: public void includeProjectMetrics(Metrics metrics) {
098: includedProjects.put(metrics.getName(), metrics);
099: }
100:
101: public Collection<String> getProjectNames() {
102: return Collections.unmodifiableCollection(includedProjects
103: .keySet());
104: }
105:
106: public Collection<Metrics> getProjectMetrics() {
107: return Collections.unmodifiableCollection(includedProjects
108: .values());
109: }
110:
111: public Collection<String> getAllProjectNames() {
112: return Collections.unmodifiableCollection(projects.keySet());
113: }
114:
115: public Collection<Metrics> getAllProjectMetrics() {
116: return Collections.unmodifiableCollection(projects.values());
117: }
118:
119: public Metrics createGroupMetrics(String name) {
120: Metrics result = groups.get(name);
121:
122: if (result == null) {
123: result = buildGroupMetrics(name);
124: groups.put(name, result);
125: }
126:
127: return result;
128: }
129:
130: private Metrics buildGroupMetrics(String name) {
131: Metrics projectMetrics = createProjectMetrics();
132: Metrics result = new Metrics(projectMetrics, name);
133:
134: populateMetrics(result, getConfiguration()
135: .getGroupMeasurements());
136: initializeGroupMetrics(name, result);
137:
138: return result;
139: }
140:
141: private void initializeGroupMetrics(String packageName,
142: Metrics metrics) {
143: computePackageNameCharacterCount(packageName, metrics);
144: computePackageNameWordCount(packageName, metrics);
145: }
146:
147: private void computePackageNameCharacterCount(String packageName,
148: Metrics metrics) {
149: metrics.addToMeasurement(Metrics.GROUP_NAME_CHARACTER_COUNT,
150: packageName.length());
151: }
152:
153: private void computePackageNameWordCount(String packageName,
154: Metrics metrics) {
155: metrics.addToMeasurement(Metrics.GROUP_NAME_WORD_COUNT, counter
156: .countPackageName(packageName));
157: }
158:
159: public void includeGroupMetrics(Metrics metrics) {
160: includedGroups.put(metrics.getName(), metrics);
161: metrics.getParent().addSubMetrics(metrics);
162: includeProjectMetrics(metrics.getParent());
163: }
164:
165: public Collection<String> getGroupNames() {
166: return Collections.unmodifiableCollection(includedGroups
167: .keySet());
168: }
169:
170: public Collection<Metrics> getGroupMetrics() {
171: return Collections.unmodifiableCollection(includedGroups
172: .values());
173: }
174:
175: public Collection<String> getAllGroupNames() {
176: return Collections.unmodifiableCollection(groups.keySet());
177: }
178:
179: public Collection<Metrics> getAllGroupMetrics() {
180: return Collections.unmodifiableCollection(groups.values());
181: }
182:
183: public Metrics createClassMetrics(String name) {
184: Metrics result = classes.get(name);
185:
186: if (result == null) {
187: result = buildClassMetrics(name);
188: classes.put(name, result);
189: }
190:
191: return result;
192: }
193:
194: private Metrics buildClassMetrics(String name) {
195: String packageName = "";
196: int pos = name.lastIndexOf('.');
197: if (pos != -1) {
198: packageName = name.substring(0, pos);
199: }
200: String className = name.substring(pos + 1);
201: Metrics packageMetrics = createGroupMetrics(packageName);
202: Metrics result = new Metrics(packageMetrics, name);
203:
204: populateMetrics(result, getConfiguration()
205: .getClassMeasurements());
206: initializeClassMetrics(className, result);
207:
208: return result;
209: }
210:
211: private void initializeClassMetrics(String className,
212: Metrics metrics) {
213: computeClassNameCharacterCount(className, metrics);
214: computeClassNameWordCount(className, metrics);
215: }
216:
217: private void computeClassNameCharacterCount(String className,
218: Metrics metrics) {
219: metrics.addToMeasurement(Metrics.CLASS_NAME_CHARACTER_COUNT,
220: className.length());
221: }
222:
223: private void computeClassNameWordCount(String className,
224: Metrics metrics) {
225: metrics.addToMeasurement(Metrics.CLASS_NAME_WORD_COUNT, counter
226: .countIdentifier(className));
227: }
228:
229: public void includeClassMetrics(Metrics metrics) {
230: includedClasses.put(metrics.getName(), metrics);
231: metrics.getParent().addSubMetrics(metrics);
232: includeGroupMetrics(metrics.getParent());
233:
234: for (String name : getConfiguration().getGroups(
235: metrics.getName())) {
236: Metrics groupMetrics = createGroupMetrics(name);
237: groupMetrics.addSubMetrics(metrics);
238: includeGroupMetrics(groupMetrics);
239: }
240: }
241:
242: public Collection<String> getClassNames() {
243: return Collections.unmodifiableCollection(includedClasses
244: .keySet());
245: }
246:
247: public Collection<Metrics> getClassMetrics() {
248: return Collections.unmodifiableCollection(includedClasses
249: .values());
250: }
251:
252: public Collection<String> getAllClassNames() {
253: return Collections.unmodifiableCollection(classes.keySet());
254: }
255:
256: public Collection<Metrics> getAllClassMetrics() {
257: return Collections.unmodifiableCollection(classes.values());
258: }
259:
260: public Metrics createMethodMetrics(String name) {
261: Metrics result = methods.get(name);
262:
263: if (result == null) {
264: result = buildMethodMetrics(name);
265: methods.put(name, result);
266: }
267:
268: return result;
269: }
270:
271: private Metrics buildMethodMetrics(String name) {
272: String className = "";
273: String featureName = "";
274: if (perl.match("/^(.*)\\.([^\\.]*)\\(.*\\)$/", name)) {
275: className = perl.group(1);
276: featureName = perl.group(2);
277: } else if (perl.match("/^(.*)\\.(static) {}$/", name)) {
278: className = perl.group(1);
279: featureName = perl.group(2);
280: } else if (perl.match("/^(.*)\\.([\\^.]*)$/", name)) {
281: className = perl.group(1);
282: featureName = perl.group(2);
283: }
284: Metrics classMetrics = createClassMetrics(className);
285: Metrics result = new Metrics(classMetrics, name);
286: classMetrics.addSubMetrics(result);
287:
288: populateMetrics(result, getConfiguration()
289: .getMethodMeasurements());
290: initializeMethodMetrics(featureName, result);
291:
292: return result;
293: }
294:
295: private void initializeMethodMetrics(String featureName,
296: Metrics metrics) {
297: computeMethodNameCharacterCount(featureName, metrics);
298: computeMethodNameWordCount(featureName, metrics);
299: }
300:
301: private void computeMethodNameCharacterCount(String featureName,
302: Metrics metrics) {
303: metrics.addToMeasurement(Metrics.METHOD_NAME_CHARACTER_COUNT,
304: featureName.length());
305: }
306:
307: private void computeMethodNameWordCount(String featureName,
308: Metrics metrics) {
309: metrics.addToMeasurement(Metrics.METHOD_NAME_WORD_COUNT,
310: counter.countIdentifier(featureName));
311: }
312:
313: public void includeMethodMetrics(Metrics metrics) {
314: includedMethods.put(metrics.getName(), metrics);
315: metrics.getParent().addSubMetrics(metrics);
316: includeClassMetrics(metrics.getParent());
317: }
318:
319: public Collection<String> getMethodNames() {
320: return Collections.unmodifiableCollection(includedMethods
321: .keySet());
322: }
323:
324: public Collection<Metrics> getMethodMetrics() {
325: return Collections.unmodifiableCollection(includedMethods
326: .values());
327: }
328:
329: public Collection<String> getAllMethodNames() {
330: return Collections.unmodifiableCollection(methods.keySet());
331: }
332:
333: public Collection<Metrics> getAllMethodMetrics() {
334: return Collections.unmodifiableCollection(methods.values());
335: }
336:
337: public void clear() {
338: projects.clear();
339: groups.clear();
340: classes.clear();
341: methods.clear();
342:
343: includedProjects.clear();
344: includedGroups.clear();
345: includedClasses.clear();
346: includedMethods.clear();
347: }
348:
349: private void populateMetrics(Metrics metrics,
350: Collection<MeasurementDescriptor> descriptors) {
351: for (MeasurementDescriptor descriptor : descriptors) {
352: try {
353: metrics.track(descriptor.createMeasurement(metrics));
354: } catch (InstantiationException ex) {
355: Logger.getLogger(getClass()).warn(
356: "Unable to create measurement \""
357: + descriptor.getShortName() + "\"", ex);
358: } catch (IllegalAccessException ex) {
359: Logger.getLogger(getClass()).warn(
360: "Unable to create measurement \""
361: + descriptor.getShortName() + "\"", ex);
362: } catch (NoSuchMethodException ex) {
363: Logger.getLogger(getClass()).warn(
364: "Unable to create measurement \""
365: + descriptor.getShortName() + "\"", ex);
366: } catch (InvocationTargetException ex) {
367: Logger.getLogger(getClass()).warn(
368: "Unable to create measurement \""
369: + descriptor.getShortName() + "\"", ex);
370: }
371: }
372: }
373:
374: public String toString() {
375: StringBuffer result = new StringBuffer();
376:
377: result.append("Factory for project \"")
378: .append(getProjectName()).append("\"").append(
379: System.getProperty("line.separator", "\n"));
380:
381: result.append("projects:").append(
382: System.getProperty("line.separator", "\n"));
383: for (Map.Entry<String, Metrics> entry : projects.entrySet()) {
384: result.append(" ").append(entry.getKey()).append(" -> ")
385: .append(entry.getValue().getName()).append("")
386: .append(System.getProperty("line.separator", "\n"));
387: }
388:
389: result.append("groups:").append(
390: System.getProperty("line.separator", "\n"));
391: for (Map.Entry<String, Metrics> entry : groups.entrySet()) {
392: result.append(" ").append(entry.getKey()).append(" -> ")
393: .append(entry.getValue().getName()).append("")
394: .append(System.getProperty("line.separator", "\n"));
395: }
396:
397: result.append("classes:").append(
398: System.getProperty("line.separator", "\n"));
399: for (Map.Entry<String, Metrics> entry : classes.entrySet()) {
400: result.append(" ").append(entry.getKey()).append(" -> ")
401: .append(entry.getValue().getName()).append("")
402: .append(System.getProperty("line.separator", "\n"));
403: }
404:
405: result.append("methods:").append(
406: System.getProperty("line.separator", "\n"));
407: for (Map.Entry<String, Metrics> entry : methods.entrySet()) {
408: result.append(" ").append(entry.getKey()).append(" -> ")
409: .append(entry.getValue().getName()).append("")
410: .append(System.getProperty("line.separator", "\n"));
411: }
412:
413: return result.toString();
414: }
415: }
|