package parser.ServletParser.library;

import java.awt.*;
import parser.ServletParser.javaparse.ParseTreeNode1;
import parser.ServletParser.*;
import java.util.*;

import java.io.*; 
import visualizer.figure.*;

/** 이 클래스는 특정 멤버 함수에 대한 정보를 관리한다.
 */
public final
class MethodInfoNode extends Object implements Serializable
{
	/** 버전 제어를 위한 시리얼 넘버이다.
	 */
	public static final long serialVersionUID = -8086152799450904778L;
	/** UNDOABLE 에 대한 상수 값이다.
	 */
   	public static final int UNDOABLE = 100;
	/** NONUNDOABLE 에 대한 상수 값이다.
	 */
	public static final int NONUNDOABLE = 200;
	/** 멤버 함수의 이름이다. 키로 사용될 수는 없다.
	 */
    private String _name;
	/** 멤버 함수의 타입이다.
	 */
    private String _type;
 	/** 멤버의 가시성을 나타낸다.
	 */
	private String _visibility;
	/** UML 스타일의 스트링이다.
	 */
	private String _umlString;
	/** UML 스타일의 스트링이다.
	 */
	private String _javaString;
	/** modifier 스트링을 저장한다.
	 */
    private String _modifierString;
	/** 인자들에 대한 정보를 관리하는 리스트 객체이다.
	 */
    private ParameterList _parameters;
	/** exception class 들에 대한 정보를 관리하는 스트링 리스트 객체이다.
	 */
	private StringList _exceptions;
	/** 함수 시그니쳐이다. 트리에서 사용된다.
	 */
	private String _asTreeNodeString;
	/** 함수 시그니쳐이다. 매개 변수의 이름은 없다.
	 */
	private String _signature;
	/** 메소드 바디에 속한 호출정보를 저장한다.
	 */
	public InstructionBlock iBlock;
	/** 메소드의 cyclomatic complexity 이다.
	 */
	private int _cyclomaticComplexity;
	/** 이 함수가 호출하는 다른 클래스에 속하는 함수의 수이다.
	 */
	private int _nRemoteCalls;
	/** 이 함수가 호출하는 다른 클래스에 속하는 unique 한 함수의 수이다.
	 */
	private int _nUniqueRemoteCalls;
	/** Number of Operands 메트릭 값 
	 */
	private int _noprnd;
	/** Number of Operators 메트릭 값 
	 */
	private int _noprtr;
	/** Number of Unique Operands 메트릭 값 
	 */
	private int _nuoprnd;
	/** Number of Unique Operators 메트릭 값 
	 */
	private int _nuoprtr;
	/** 메소드에서 사용된 데이터 멤버의 리스트이다.
	 */
	public StringList usedDataMembers;
	/** 이 메소드에서 PrinterWriter에 의해 출력되는 HTML 스트링 들이다.
	 */
	public StringList htmlText; 
	/** 출력된 HTML 파일의 이름이다.
	 */
	public String htmlFileName;
	/** 출력된 HTML 파일의 이름이다.
	 */
	public String htmlShortFileName;
	/** 이 메소드에서 사용된 모든 sql 정보의 모음이다.
	 */
	public SQLInfoList sqlList;
	/** 이 메소드 body 이다.
	 */
	public StringList methodBody; 
	/** 생성자이다.
	 */
    public MethodInfoNode(String name) {
		_name = new String(name);
		_type = "";
		_visibility = "";
		_umlString = "";
		_modifierString = "";
		_javaString = "";
		_signature = "";
		_asTreeNodeString = "";
		_parameters = new ParameterList();
		_exceptions = new StringList();
		iBlock = new InstructionBlock();
		_nUniqueRemoteCalls = 0;
		_nRemoteCalls = 0;
		_noprnd = 0;
		_noprtr = 0;
		_nuoprnd = 0;
		_nuoprtr = 0;
		usedDataMembers = new StringList();
		htmlText = new StringList();
		htmlFileName = "";
		htmlShortFileName = "";
 		sqlList = new SQLInfoList();
		methodBody = new StringList();
   }
	public void writeHTMLFileIfPossible(String className,String packName) {
		if (htmlText.nOfList() == 0) return;
		String fName = ServletParser.getHTMLFilesPath()+ packName + "_" + className + "." + _name + ".html";
		String shortName = className + "." + _name /*+ ".html"*/;

		try {
			FileWriter writer = new FileWriter(fName);

			String htmlLine = htmlText.getFirst();
			while (htmlLine != null) {
				writer.write(htmlLine+"\r\n");
				htmlLine = htmlText.getNext();
			}
			writer.close();
			htmlFileName = new String(fName);
			htmlShortFileName = new String(shortName);
		} catch (IOException e) {
			System.err.println(e.toString());
		}
	}
	public void addHtmlString(String s) {
		htmlText.addTail(s);
	}
	public void addMethodBody(String aLine) {
		methodBody.addTail(aLine);
	}
	public void calcRemoteMethodCalls(StringList allMethods) {
		StringList remoteMethods = new StringList();
		_nRemoteCalls = iBlock.collectRemoteCalls(remoteMethods,allMethods);
		_nUniqueRemoteCalls = remoteMethods.nOfList();
	}
	public int getNumberOfUniqueRemoteCalls() {
		return _nUniqueRemoteCalls;
	}
	public void gatherRemoteMethodCalls(StringList remoteMethods,StringList allMethods) {
		iBlock.collectRemoteCalls(remoteMethods,allMethods);
	}
	public int getNumberOfRemoteCalls() {
		return _nRemoteCalls;
	}
	/** 데이터 멤버 _name에 대한 write access 함수이다.
	 */
	public void setName(String val) {
		_name = new String(val);
	}
	/** 데이터 멤버 _name에 대한 read access 함수이다.
	 */
	public String getName() {
		return _name;
	}
	/** 데이터 멤버 _name에 대한 read access 함수이다.
	 */
	public String getMethodName() {
		return getName();
	}
	/** 데이터 멤버 _type에 대한 write access 함수이다.
	 */
	public void setType(String val) {
		if (val == null) {
			_type = "";
		} else {
			_type = new String(val);
		}
	}
	/** 데이터 멤버 _type에 대한 read access 함수이다.
	 */
	public String getType() {
		return _type;
	}
	/** 데이터 멤버 _exceptions에 exception 클래스 이름들을 추가하는 함수이다.
	 */
	public void addExceptions(ParseTreeNode1 exs) {
		if (exs == null) return;
		ParseTreeNode1 anEx = exs;
		while (anEx != null) {
			_exceptions.insert(anEx.value);
			anEx = anEx.siblings;
		}
	}
	/** 데이터 멤버 _exceptions에 대한 read access 함수이다.
	 */
	public StringList getExceptions() {
		return _exceptions;
	}
	/** 데이터 멤버 _type에 대한 read access 함수이다.
	 */
	public String getReturnType() {
		return getType();
	}
	/** 데이터 멤버 _parameters에 대한 read access 함수이다.
	 */
	public ParameterList getParameters() {
		return _parameters;
	}
	/** 데이터 멤버 _visibility에 대한 write access 함수이다.
	 */
	public void setVisibility(String modifierString) {
		if (modifierString == null) {
			_visibility = "+";
		} else if (modifierString.length() > 0) {
			char vis = modifierString.charAt(0);
			if (vis == '+') {
				_visibility = "+";
			} else if (vis == '#') {
				_visibility = "#";
			} else if (vis == '-') {
				_visibility = "-";
			}
		}
	}
	/** 데이터 멤버 _visibility에 대한 read access 함수이다.
	 */
	public String getVisibility() {
		return _visibility;
	}
	/** 데이터 멤버 _visibility에 대한 read access 함수이다. ("","public","private","protected")
	 */
	public String getAccessSpecifier() {
		if (_visibility != null && _visibility.length() > 0) {
			if (_visibility.equals("+")) {
				return new String("public"); 
			} else if (_visibility.equals("#")) {
				return new String("protected"); 
			} else if (_visibility.equals("-")) {
				return new String("private"); 
			}
		}
		return new String(""); // default visibility
	}
	/** UML 스타일의 스트링을 만드는 함수이다.
	 */
	public void makeUMLString() {
		_umlString = new String("");
		if (_visibility != null && _visibility.length() > 0) {
			_umlString = _umlString + _visibility;
		}
		_umlString = _umlString + _name;
		_umlString = _umlString + "(";
		String args = _parameters.getUMLString();
		_umlString = _umlString + args;
		_umlString = _umlString + ")";
		if (_type != null && _type.length() > 0) {
			_umlString = _umlString + ":" + _type;
		}

		makeSignature();
		// modifier에 대한 처리 필요함: ETRI와 연락후에 ...
		// ...
		makeJavaString();
	}
	/** 데이터 멤버 _umlString에 대한 read access 함수이다.
	 */
	public String getUMLString() {
		return _umlString;
	}
	/** Java 스타일의 스트링을 만드는 함수이다.
	 */
	public void makeJavaString() {
		_javaString = new String("");
		if (_visibility != null && _visibility.length() > 0) {
			if (_visibility.equals("+")) {
				_javaString = "public ";
			} else if (_visibility.equals("#")) {
				_javaString = "protected ";
			} else if (_visibility.equals("-")) {
				_javaString = "private ";
			}
		}
		if (_modifierString != null && _modifierString.length() > 0) {
			_javaString = _javaString + _modifierString + " ";
		}
		if (_type != null && _type.length() > 0) {
			_javaString = _javaString + _type + " ";
		}
		_javaString = _javaString + _name;
		_javaString = _javaString + "(";
		String args = _parameters.getJavaString();
		_javaString = _javaString + args;
		_javaString = _javaString + ")";

		_asTreeNodeString = new String("");
		_asTreeNodeString = _asTreeNodeString + _name;
		_asTreeNodeString = _asTreeNodeString + "(";
		_asTreeNodeString = _asTreeNodeString + args;
		_asTreeNodeString = _asTreeNodeString + ")";
	}
	/** 데이터 멤버 _asTreeNodeString 대한 read access 함수이다.
	 */
	public String getAsTreeNodeString() {
		return _asTreeNodeString;
	}
	/** 데이터 멤버 _javaString에 대한 read access 함수이다.
	 */
	public String getJavaString() {
		return _javaString;
	}
	/** 데이터 멤버 _modifierString에 대한 write access 함수이다.
	 */
	public void setModifierString(String val) {
		if (val == null) {
			_modifierString = "";
		} else if (val.length() <= 1) {
			_modifierString = "";
		} else if (val.length() > 1) {
			char vis = val.charAt(0);
			if (vis == '+' || vis == '#' || vis == '-') {
				_modifierString = new String(val.substring(2));
			} else {
				_modifierString = new String(val);
			}
		}
	}
	/** _cyclomaticComplexity에 대한 write access 함수이다.
	 */
	public void setCyclomaticComplexity(int n) {
		_cyclomaticComplexity = n;
	}
	/** _cyclomaticComplexity에 대한 read access 함수이다.
	 */
	public int getCyclomaticComplexity() {
		return _cyclomaticComplexity;
	}
	/** 데이터 멤버 _modifierString에 대한 read access 함수이다.
	 */
	public String getModifierString() {
		return _modifierString;
	}
	/** 데이터 멤버 _nOfArguments에 대한 read access 함수이다.
	 */
	public int getNOfArguments() {
		return _parameters.nOfList();
	}
	/** _noprnd에 대한 write access 함수이다.
	 */
	public void setNoprnd(int n) {
		if (n < 0) n = 0;
		_noprnd = n;
	}
	/** _noprnd에 대한 read access 함수이다.
	 */
	public int getNOperands() {
		return _noprnd;
	}
	/** _noprtr에 대한 write access 함수이다.
	 */
	public void setNoprtr(int n) {
		if (n < 0) n = 0;
		_noprtr = n;
	}
	/** _noprtr에 대한 read access 함수이다.
	 */
	public int getNOperators() {
		return _noprtr;
	}
	/** _noprnd에 대한 write access 함수이다.
	 */
	public void setNuoprnd(int n) {
		if (n < 0) n = 0;
		_nuoprnd = n;
	}
	/** _noprnd에 대한 read access 함수이다.
	 */
	public int getNUniqueOperands() {
		return _nuoprnd;
	}
	/** _noprtr에 대한 write access 함수이다.
	 */
	public void setNuoprtr(int n) {
		if (n < 0) n = 0;
		_nuoprtr = n;
	}
	/** _noprtr에 대한 read access 함수이다.
	 */
	public int getNUniqueOperators() {
		return _nuoprtr;
	}
	/** 이 함수는 파스트리로 부터 인자 리스트를 구축한다.
	 */
	public void makeArgList(ParseTreeNode1 parameters) {
		if (parameters == null) return;
		ParseTreeNode1 paraNode = parameters;
		while (paraNode != null) {
			ParameterInfo info = new ParameterInfo(paraNode.siblings.value,paraNode.value);
			_parameters.insert(info);
			paraNode = paraNode.children;
		}
	} 
	/** 시그니쳐 스트링을 만드는 함수이다.
	 */
	private void makeSignature() {
		_signature = new String("");
		_signature = _signature + _name + "(";
		String args = _parameters.getTypesString();
		_signature = _signature + args;
		_signature = _signature + ")";
	}
	/** 메소드 비교하는 함수이다.
	 */
	public boolean exactMatches(String name,String type,StringList argTypes) {
		if (name.compareTo(_name) != 0) return false;
		if (type != null && // 이 경우는 리턴 타입을 고려하지 않는 경우임
			type.compareTo(_type) != 0) return false;
		if (argTypes.nOfList() != _parameters.nOfList()) return false;
		String argType = argTypes.getFirst();
		ParameterInfo paraType = _parameters.getFirst();
		while(argType != null) {
			if (argType.compareTo(paraType.getType()) != 0) return false;
			argType = argTypes.getNext();
			paraType = _parameters.getNext();
		}
		return true;
	}
	/** _signature 에 대한 read access function 이다.
	 */
	public String getSignature() {
		return _signature;
	}
	/** 리턴 타입없이 메소드 비교하는 함수이다.
	 */
	public boolean exactMatchesNoReturnType(String name,StringList argTypes) {
		if (name.compareTo(_name) != 0) return false;
		if (argTypes.nOfList() != _parameters.nOfList()) return false;
		String argType = argTypes.getFirst();
		ParameterInfo paraType = _parameters.getFirst();
		while(argType != null) {
			if (argType.compareTo(paraType.getType()) != 0) return false;
			argType = argTypes.getNext();
			paraType = _parameters.getNext();
		}
		return true;
	}
	/** 리턴 타입없이 인자수를 이용하여 메소드 비교하는 함수이다.
	 */
	public boolean matchesNArgNoReturnType(String name,StringList argTypes) {
		if (name.compareTo(_name) != 0) return false;
		if (argTypes.nOfList() != _parameters.nOfList()) return false;
		return true;
	}
	/** 조인 테이블 경우 필드가 어느 테이블에 속하는지 결정하는 함수이다.
	 */
	public void determineAmbiguousFieldNamesForJoinTablesAndCollectSQL(SQLTableInfoList allTableInfos,SQLInfoList classSqlList) {
		iBlock.determineAmbiguousFieldNamesForJoinTablesAndCollectSQL(allTableInfos,classSqlList,sqlList);
	}
	public int drawCascadeMessages(GraphicController controller,SFDObject fromObject,
							SFDObjectList objectList,StringList calledStringList,int startY,int vGap) {
		if (iBlock.hasNoCall() == true)
            return startY;

		return iBlock.drawCascadeMessages(controller,fromObject,objectList,calledStringList,startY,vGap);
	}
	/** 테스트 용 함수
	public void printCallGraph(FileWriter writer,String senderClass,String senderObject) {
		if (iBlock.hasNoCall() == true) return;
try
{
	writer.write("========== begin "+getUMLString()+" ==========\r\n");
		iBlock.printCallGraph(writer,senderClass,senderObject);
	writer.write("========== end "+getUMLString()+" ==========\r\n");
}
catch (IOException e)
{
}
	}
	 */
}
