/*
 * FindBugs - Find Bugs in Java programs
 * Copyright (C) 2005, University of Maryland
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package edu.umd.cs.findbugs.model;

import java.util.Iterator;

import edu.umd.cs.findbugs.FieldAnnotation;
import edu.umd.cs.findbugs.MethodAnnotation;
import edu.umd.cs.findbugs.ba.SignatureParser;

/**
 * Utility methods for using a ClassNameRewriter.
 * 
 * @author David Hovemeyer
 */
public abstract class ClassNameRewriterUtil {

	/**
	 * Rewrite a method signature.
	 * 
	 * @param classNameRewriter a ClassNameRewriter
	 * @param methodSignature   a method signature
	 * @return the rewritten method signature
	 */
	public static String rewriteMethodSignature(ClassNameRewriter classNameRewriter, String methodSignature) {
		if (classNameRewriter != IdentityClassNameRewriter.instance()) {
			SignatureParser parser = new SignatureParser(methodSignature);

			StringBuilder buf = new StringBuilder();

			buf.append('(');
			for (Iterator<String> i = parser.parameterSignatureIterator(); i.hasNext();) {
				buf.append(rewriteSignature(classNameRewriter, i.next()));
			}

			buf.append(')');
			buf.append(rewriteSignature(classNameRewriter, parser.getReturnTypeSignature()));

			methodSignature = buf.toString();
		}

		return methodSignature;
	}

	/**
	 * Rewrite a signature.
	 * 
	 * @param classNameRewriter a ClassNameRewriter
	 * @param signature         a signature (parameter, return type, or field)
	 * @return rewritten signature with class name updated if required
	 */
	public static String rewriteSignature(ClassNameRewriter classNameRewriter, String signature) {
		if (classNameRewriter != IdentityClassNameRewriter.instance()
				&& signature.startsWith("L")) {

			String className = signature.substring(1, signature.length() - 1).replace('/', '.');
			className = classNameRewriter.rewriteClassName(className);

			signature = "L" + className.replace('.', '/') + ";";
		}

		return signature;
	}

	/**
	 * Rewrite a MethodAnnotation to update the class name,
	 * and any class names mentioned in the method signature.
	 * 
	 * @param classNameRewriter a ClassNameRewriter
	 * @param annotation        a MethodAnnotation
	 * @return the possibly-rewritten MethodAnnotation
	 */
	public static MethodAnnotation convertMethodAnnotation(ClassNameRewriter classNameRewriter, MethodAnnotation annotation) {

		if (classNameRewriter != IdentityClassNameRewriter.instance()) {
			annotation = new MethodAnnotation(
					classNameRewriter.rewriteClassName(annotation.getClassName()),
					annotation.getMethodName(),
					rewriteMethodSignature(classNameRewriter, annotation.getMethodSignature()),
					annotation.isStatic());
		}
		return annotation;
	}

	/**
	 * Rewrite a FieldAnnotation to update the class name
	 * and field signature, if needed.
	 * 
	 * @param classNameRewriter a ClassNameRewriter
	 * @param annotation        a FieldAnnotation
	 * @return the possibly-rewritten FieldAnnotation
	 */
	public static FieldAnnotation convertFieldAnnotation(ClassNameRewriter classNameRewriter, FieldAnnotation annotation) {

		if (classNameRewriter != IdentityClassNameRewriter.instance()) {
			annotation = new FieldAnnotation(
					classNameRewriter.rewriteClassName(annotation.getClassName()),
					annotation.getFieldName(),
					rewriteSignature(classNameRewriter, annotation.getFieldSignature()),
					annotation.isStatic());
		}
		return annotation;
	}

}
