/******************************************************************************* * Copyright (c) 2008 Anyware Technologies and others. * 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: * Philippe Roland (Atos) - initial API and implementation *******************************************************************************/ package org.eclipse.umlgen.reverse.java.logging; import java.text.SimpleDateFormat; import java.util.Calendar; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.emf.ecore.EModelElement; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.VariableDeclarationStatement; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.NamedElement; import org.eclipse.uml2.uml.Package; import org.eclipse.umlgen.reverse.java.internal.ReversePlugin; /** * Logging Utilities. */ public class LogUtils { /** Logger object. */ private static ILog logger = ReversePlugin.getDefault().getLog(); /** Initial tabbing. */ private static String tabbedSpace = ""; /** Tabbing increment for indentation. */ private static String tabIncrement = " "; /** Level of log. */ private static int logLevel = IStatus.INFO; /** * Reset tabbing. */ public static void resetTabbing() { tabbedSpace = ""; } /** * Increment tabbing. */ public static void incrementTabbing() { tabbedSpace += tabIncrement; } /** * Decrement tabbing. */ private static void decreaseTabbing() { if (tabbedSpace.length() >= tabIncrement.length()) { tabbedSpace = tabbedSpace.substring(tabIncrement.length()); } } /** * Gets the type and name of an object. Can handle UML Elements and JDT IJavaElements. * * @param object * an object * @return the object's full name */ public static String getFullName(Object object) { if (object instanceof IJavaElement) { return "Java " + getTypeName(object) + " " + ((IJavaElement)object).getElementName(); } else if (object instanceof Element) { String umlName = getUMLName((Element)object); return "UML " + object.getClass().getSimpleName() + " " + umlName; } else if (object instanceof ASTNode) { return "AST " + getTypeName(object) + " " + getAstName((ASTNode)object); } return null; } /** * Return the package of the class. * * @param clazz * @return the package */ private static Package getClassPackage(Class clazz) { Element parent = clazz.getOwner(); while (parent != null && !(parent instanceof Package)) { parent = parent.getOwner(); } return (Package)parent; } /** * Get first ancestor of element that is a class or a package. * * @param el * an element * @return its first ancestor that is a class or a package */ private static Element getFirstClassOrPackageOwner(Element el) { Element parent = el.getOwner(); while (parent != null && !(parent instanceof Package) && !(parent instanceof Class)) { parent = parent.getOwner(); } return parent; } /** * Create a log entry for a diff merge annotation. States the element to be added/deleted and its * immediate ancestry (class + package) * * @param diff * @param isAdd */ public static void logDiffMergeAnnotation(EModelElement diff, boolean isAdd) { if (diff instanceof Element) { StringBuffer msgBuffer = new StringBuffer(tabbedSpace); msgBuffer.append(getFullName(diff)); msgBuffer.append(" is "); msgBuffer.append(isAdd ? "added " : "deleted "); Element el = getFirstClassOrPackageOwner((Element)diff); if (el != null) { msgBuffer.append("within "); msgBuffer.append(getFullName(el)); if (el instanceof Class) { Package pack = getClassPackage((Class)el); msgBuffer.append("in " + getFullName(pack)); } } doLog(IStatus.INFO, msgBuffer.toString()); } } /** * Create a log entry for element creation. sourceContainer , source and comment are optional. * * @param sourceContainer * @param source * @param createdElement * @param comment */ public static void logCreation(Object sourceContainer, Object source, Object createdElement, String comment) { StringBuffer msgBuffer = new StringBuffer(); if (source != null && createdElement != null) { String sourceName = getFullName(source); String createdFullName = getFullName(createdElement); if (sourceName != null && createdFullName != null) { // source type and name msgBuffer.append(tabbedSpace + sourceName); // if a container is given, add its type and name if (sourceContainer != null) { String containerName = getFullName(sourceContainer); if (containerName != null) { msgBuffer.append(" within " + containerName); } } // type and name (if it exists) of the created object msgBuffer.append(" was translated as " + createdFullName); // add a comment if given if (comment != null) { msgBuffer.append(": " + comment); } doLog(IStatus.INFO, msgBuffer.toString()); return; } } else if (createdElement != null) { // type and name (if it exists) of the created object String sourceName = getFullName(createdElement); msgBuffer.append(tabbedSpace + sourceName + " was created"); // if a container is given, add its type and name if (sourceContainer != null) { String containerName = getFullName(sourceContainer); if (containerName != null) { msgBuffer.append(" within " + containerName); } } // add a comment if given if (comment != null) { msgBuffer.append(": " + comment); } doLog(IStatus.INFO, msgBuffer.toString()); return; } } /** * Log the act of a visitor entering an object. * * @param object * the object * @param comment * the comment */ public static void logEntering(Object object, String comment) { StringBuffer msgBuffer = new StringBuffer(); if (object != null) { String fullName = getFullName(object); if (fullName != null) { // type and name (if it exists) of the created object msgBuffer.append(tabbedSpace + "Entering " + fullName); // add a comment if given if (comment != null) { msgBuffer.append(": " + comment); } doLog(IStatus.INFO, msgBuffer.toString()); incrementTabbing(); } return; } } /** * Log the act of a visitor exiting an object. */ public static void logExiting() { decreaseTabbing(); } /** * Log a free comment. * * @param comment * a string comment */ public static void logMessage(String comment) { if (comment != null) { doLog(IStatus.WARNING, comment); } } /** * Log a throwable element. * * @param throwable * the throwable element */ public static void logThrowable(Throwable throwable) { if (logLevel <= IStatus.INFO) { String mess = throwable.getMessage(); if (mess == null) { mess = ""; } StringBuffer msgBuffer = new StringBuffer(mess); StackTraceElement[] stackTrace = throwable.getStackTrace(); for (StackTraceElement el : stackTrace) { msgBuffer.append("\n" + el.toString()); } doLog(IStatus.ERROR, msgBuffer.toString()); } else { doLog(IStatus.ERROR, throwable.getMessage()); } } /** * Log a new Status with the given level and message. * * @param level * the level * @param message * a message */ private static void doLog(int level, String message) { final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); String date = dateFormat.format(Calendar.getInstance().getTime()); if (message != null && level >= logLevel) { logger.log(new Status(level, ReversePlugin.getId(), date + ": " + message)); } } /** * Return the name of the createdElement. * * @param createdElement * @return the name */ private static String getUMLName(Element createdElement) { // TODO handle relationships if (createdElement instanceof NamedElement) { return ((NamedElement)createdElement).getName(); } else { return "unnamed"; } } /** * Returns the name of the node. * * @param node * @return the name */ private static String getAstName(ASTNode node) { String name = null; switch (node.getNodeType()) { case ASTNode.COMPILATION_UNIT: name = ((CompilationUnit)node).getJavaElement().getElementName(); break; case ASTNode.METHOD_DECLARATION: name = ((MethodDeclaration)node).getName().getIdentifier(); break; case ASTNode.METHOD_INVOCATION: name = ((MethodInvocation)node).getName().getIdentifier(); break; case ASTNode.VARIABLE_DECLARATION_STATEMENT: // TODO can we improve on this? name = ((VariableDeclarationStatement)node).toString().trim(); break; case ASTNode.EXPRESSION_STATEMENT: // TODO can we improve on this? name = ((ExpressionStatement)node).toString().trim(); break; default: name = node.toString().trim(); } return name; } /** * Returns the name of the element. * * @param element * @return the name */ private static String getTypeName(Object element) { String className = element.getClass().getSimpleName(); return className == null ? "element" : className; } /** * Set minimum logging level. * * @param iLogLevel * the desired minimum logging level */ public static void setLogLevel(int iLogLevel) { logLevel = iLogLevel; } }