/*
 *   Copyright 2003-2004 The Apache Software Foundation.
// (c) Copyright IBM Corp. 2004, 2005 All Rights Reserved
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package org.apache.axis.tools.common;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * A C or C++ method signature with the ability to parse it.
 * TODO: properly support variable length argument lists using "..."
 * TODO: passing or returning function pointers (hopefully not needed)
 * TODO: Cope with ~<space>Classname()
 */
public class Signature {
	private String originalText;
	private String attributes;
	private String className = null;
	private String methodName = null;
	private Parameter returnType = null;
	private Parameter[] params = null;
	private String trailingAttributes;
	private String scope = "public";
	private boolean failed = false;
	private boolean traceable = true;

	private final static Set knownAttrs =
		new HashSet(
			Arrays.asList(
				new Object[] {
					"public",
					"private",
					"extern",
					"\"C\"",
					"virtual",
					"static",
					"inline" }));

	private final static Set specialOperators =
		new HashSet(
			Arrays.asList(
				new Object[] { "(", ")", "*", ",", "&", "]", "[", "=", "~" }));

	/**
	 * Takes an unparsed signature string and parses it.
	 *
	 * TODO: Should optionally pass in the className here in case it's an 
	 * inline method implementation inside the class{}. Just so the className
	 * comes out in the trace.
	 */
	Signature(String s) {
		originalText = s;

		try {
			List tokens = tokenise(s);

			ArrayList alAttrs = new ArrayList();
			ArrayList alName = new ArrayList();
			ArrayList alParms = new ArrayList();
			ArrayList alTrailAttrs = new ArrayList();
			ArrayList alInits = new ArrayList();
			if (!splitUp(tokens,
				alAttrs,
				alName,
				alParms,
				alTrailAttrs,
				alInits)) {
				failed = true;
				return;
			}

			parseAttributes(alAttrs);
			parseNameAndRetType(alName);
			parseParameters(alParms);
			parseTrailingAttributes(alTrailAttrs);

			// Ignore any tokens after the ) since these are (hopefully) 
			// constructor initialisers

			traceable = !Configuration.methodExcluded(className, methodName);
		} catch (NullPointerException npe) {
			failed = true;
			traceable = false;
		}
	}

	/**
	 * Parse the signature into tokens. This removes whitespace and comments
	 * and separates out "*", ",", "(", ")", "&", "[" and "]".
	 */
	private static List tokenise(String s) {
		ArrayList tokens = new ArrayList();
		String tok = null;
		boolean space = true;
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (Character.isWhitespace(c)) {
				space = true;
				continue;
			}
			if (space) {
				if (tok != null)
					tokens.add(tok);
				tok = "" + c;
			} else
				tok += c;
			space = false;

			if (tok.endsWith("/*")) {
				String sub = s.substring(i);
				int endcomm = sub.indexOf("*/");
				if (endcomm == -1)
					break;
				i += endcomm + 1;
				if (tok.equals("/*"))
					tok = "";
				else
					tok = tok.substring(0, tok.length() - 2);
				continue;
			}

			if (tok.endsWith("//")) {
				String sub = s.substring(i);
				int endcomm = sub.indexOf("\n");
				if (endcomm == -1)
					break;
				i += endcomm;
				if (tok.equals("//"))
					tok = "";
				else
					tok = tok.substring(0, tok.length() - 1);
				continue;
			}

			if (tok.endsWith("::"))
				space = true;

			String sc = "" + c;
			if (specialOperators.contains(sc)) {
				if (!tok.equals(sc)) {
					tokens.add(tok.substring(0, tok.length() - 1));
					tok = sc;
				}
				space = true;
			}
		}
		tokens.add(tok);
		return tokens;
	}

	/**
	 * Split up a tokenised method signature into a list of attributes, a list of 
	 * name and return type tokens, a list of parameter tokens and a list of 
	 * initialiser tokens. 
	 */
	private static boolean splitUp(
		List tokens,
		List attrs,
		List nameAndRet,
		List parms,
		List trailAttrs,
		List inits) {

		// nameStart points to the start of the return type if there is one
		// else the start of the method name
		int nameStart;
		for (nameStart = 0; nameStart < tokens.size(); nameStart++) {
			String tok = (String) (tokens.get(nameStart));
			if (!knownAttrs.contains(tok) && !Configuration.isAttribute(tok))
				break;
            }
		if (nameStart == tokens.size())
			return false;

		// initStart points to the initialisers, or thrown exceptions after 
		// the parameter list. throw is a keyword so we can safely search for it.
		int initStart = tokens.size();
		for (int i = nameStart; i < tokens.size(); i++) {
			String tok = (String) tokens.get(i);
			if ((tok.startsWith(":") && !tok.startsWith("::"))
				|| "throw".equals(tok))
				initStart = i;
		}

		int parmEnd;
		for (parmEnd = initStart - 1; parmEnd > nameStart; parmEnd--)
			if (")".equals(tokens.get(parmEnd)))
				break;
		if (parmEnd == nameStart)
			return false;

		int parmStart = parmEnd;
		for (parmStart = parmEnd; parmStart > nameStart; parmStart--)
			if ("(".equals(tokens.get(parmStart)))
				break;

		for (int i = 0; i < tokens.size(); i++) {
			Object tok = tokens.get(i);
			if (i < nameStart || Configuration.isAttribute((String) tok))
				attrs.add(tok);
			else if (i < parmStart)
				nameAndRet.add(tok);
			else if (i <= parmEnd)
				parms.add(tok);
			else if (i < initStart)
				trailAttrs.add(tok);
			else
				inits.add(tok);
		}
		return true;
	}

	private void parseAttributes(List list) {
		attributes = new String();
		Iterator it = list.iterator();
		while (it.hasNext()) {
			if (attributes.length() > 0)
				attributes += " ";
			String next = (String) it.next();
			if ("public".equals(next)
				|| "protected".equals(next)
				|| "private".equals(next))
				scope = next;
			attributes += next;
		}
	}

	private void parseNameAndRetType(List list) {
		int size = list.size();
		int idx;
		// "operator" is a key word so if it's present we know we're
		// dealing with operator overloading. The operator that's been
		// overloaded might have been split up into multiple tokens.
		for (idx = 0; idx < size; idx++)
			if ("operator".equals(list.get(idx)))
				break;

		if (idx < size) {
			methodName = "";
			for (int i = idx; i < size; i++)
				methodName += (String) list.get(i);
		} else { // No operator overloading
			methodName = "" + list.get(size - 1);
			idx = size - 1;
		}

		// If it's a destructor, the "~" will be split out into a separate
		// token, so add it onto the methodName here.
		if (idx > 0 && "~".equals(list.get(idx - 1))) {
			methodName = "~" + methodName;
			idx--;
		}

		// The class name comes before the method name
		while (idx > 0 && ((String) list.get(idx - 1)).endsWith("::")) {
			if (null == className)
				className = (String) list.get(idx - 1);
			else
				className = (String) list.get(idx - 1) + className;
			idx--;
		}

		// Whatever's left before the classname/methodname must be the 
		// return type
		ArrayList retParm = new ArrayList();
		for (int i = 0; i < idx; i++)
			retParm.add(list.get(i));

		returnType = new Parameter(retParm, true);
	}

	/**
	 * Constructs the parameter list
	 */
	private void parseParameters(List list) {
		ArrayList alParams = new ArrayList();
		Iterator it = list.iterator();
		String token = (String) it.next(); // step over the (
		while (it.hasNext() && !")".equals(token)) {
			token = (String) it.next();

			int template = 0; // Depth of template scope
			boolean foundEquals = false;
			// Ignore default value for an optional parameter
			ArrayList parm = new ArrayList();
			while (!token.equals(")")
				&& (!token.equals(",") || template > 0)) {
				if (token.equals("="))
					foundEquals = true;
				if (!foundEquals)
					parm.add(token);
				if (contains(token, "<"))
					template++;
				if (contains(token, ">"))
					template--;
				token = (String) it.next();
			}

			// No parameters so break out
			if (token.equals(")") && 0 == parm.size())
				break;

			Parameter p = new Parameter(parm);
			if (p.failed()) {
				failed = true;
				return;
			}

			// Copes with void func(void)
			if (!p.isVoid())
				alParams.add(p);
		}

		int size = alParams.size();
		if (size > 0) {
			params = new Parameter[size];
			System.arraycopy(alParams.toArray(), 0, params, 0, size);
		}
	}

	private void parseTrailingAttributes(List list) {
		trailingAttributes = new String();
		Iterator it = list.iterator();
		while (it.hasNext()) {
			if (trailingAttributes.length() > 0)
				trailingAttributes += " ";
			trailingAttributes += (String) it.next();
		}
	}

	public String getOriginal() {
		return originalText;
	}

	public int originalLength() {
		return originalText.length();
	}

	public boolean failed() {
		return failed;
	}

	public String getAttributes() {
		return attributes;
	}

	public String getClassName() {
		return className;
	}

	public String getTrimClassName() {
		return trimClassName(className);
	}

	public String getMethodName() {
		return methodName;
	}

	public Parameter getReturnType() {
		return returnType;
	}

	public Parameter[] getParameters() {
		return params;
	}
	
	public boolean isConstructor() {
		return className != null
			&& methodName != null
			&& trimClassName(className).equals(methodName);
	}

	public boolean isDestructor() {
		return className != null
			&& methodName != null
			&& methodName.startsWith("~")
			&& methodName.endsWith(trimClassName(className));
	}
	
	private static String trimClassName(String name) {
		if (name.endsWith("::"))
			return name.substring(0, name.length() - 2);
		return name;
	}

	void setClassName(String className) {
		if (null == className)
			return;
		if (!className.endsWith("::"))
			className += "::";
		this.className = className;
	}
	
	public String getScope() {
		return scope;
	}

    /**
     * Sets the scope, but only if the scope is not set by an explicit
     * attribute in the signature.
     */
	public void setScope(String scope) {
		if (-1 == attributes.indexOf(this.scope))
			this.scope = scope;
	}

	/**
	 * Should this method be traced?
	 */
	public boolean traceable() {
		return traceable;
	}

	private static boolean contains(String src, String tgt) {
		if (src == null || tgt == null)
			return false;
		if (-1 == src.indexOf(tgt))
			return false;
		return true;
	}

	public boolean equals(Object obj) {
		if (null == obj || !(obj instanceof Signature))
			return false;
		Signature that = (Signature) obj;
		if (!Utils.safeEquals(className, that.className))
			return false;
		if (!Utils.safeEquals(methodName, that.methodName))
			return false;
		if (!Utils.safeEquals(returnType, that.returnType))
			return false;
		if (null == params && null == that.params)
			return true;
		if (null != params && null == that.params)
			return false;
		if (null == params && null != that.params)
			return false;
		if (params.length != that.params.length)
			return false;
		for (int i = 0; i < params.length; i++)
			if (!Utils.safeEquals(params[i], that.params[i]))
				return false;
		return true;
	}

	public String toStringWithoutAttrs() {
		String s = new String();
		if (returnType != null)
			s += returnType + " ";
		if (className != null)
			s += className;
		s += methodName + "(";
		for (int i = 0; params != null && i < params.length; i++) {
			if (i > 0)
				s += ", ";
			s += params[i].toString();
		}
		s += ")";
		return s;
	}

	public String toString() {
		String s = attributes;
		if (attributes.length() > 0)
			s += " ";
		s += toStringWithoutAttrs();
		if (trailingAttributes.length() > 0)
			s += " " + trailingAttributes;
		return s;
	}
}
