package jp.hasc.hasctool.ui.views.beanslist;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import com.thoughtworks.xstream.annotations.XStreamAsAttribute;

/**
 * Beanのクラス
 * @author iwasaki
 */
public class BeanClass {
	/** logger for this class */
	private final static org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
			.getLog(BeanClass.class);
	
	public static final String METHOD_NAME_LABEL = "getRuntimeBeanLabel";
	public static final String METHOD_NAME_DESCRIPTION = "getRuntimeBeanDescription";
	
	/** パッケージ名まで含めたクラス名 */
	@XStreamAsAttribute
	private String className=null;
	
	private transient String label_=null;

	private transient BeansFolder parentFolder=null;
	
	public BeanClass(String className) {
		this.className=className;
	}

	public BeanClass(Class<?> cls) {
		this.className=cls.getName();
	}
	
	public String getClassName() {
		return className;
	}
	
	public static String getBeanClassDescriptionOrNull(Class<?> cls) {
		Method m = getStaticNoParameterMethod(cls,METHOD_NAME_DESCRIPTION,String.class);
		if (m!=null) {
			try {
				return ((String)m.invoke(null));
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return null;
	}

	public String getLabel() {
		if (label_==null) {
			try{
				Class<?>cls=Class.forName(className);
				
				// get label
				{
					Method m = getStaticNoParameterMethod(cls,METHOD_NAME_LABEL,String.class);
					if (m!=null) {
						label_ = (String)m.invoke(null);
					}else{
						label_=cls.getSimpleName();
					}
				}
				
				// get description
				{
					String desc=getBeanClassDescriptionOrNull(cls);
					if (desc!=null) {
						label_ += " - " + desc;
					}
				}
				
				return label_;
				
			}catch(Exception ex) {
				LOG.warn("Exception",ex);
				label_="[Error] "+className;
			}
		}
		return label_;
	}

	public static Method getStaticNoParameterMethod(Class<?> cls, String name, Class<?> returnType) {
		for(Method m : cls.getMethods()) {
			if (m.getName().equals(name) && Modifier.isStatic(m.getModifiers()) && 
					m.getDeclaringClass().equals(cls) &&
					m.getReturnType().equals(returnType) && m.getParameterTypes().length==0)
			{
				return m;
			}
		}
		return null;
	}

	public BeansFolder getParentFolder() {
		return parentFolder;
	}

	public void setParentFolder(BeansFolder parentFolder) {
		this.parentFolder = parentFolder;
	}

	public boolean matchToSearcher(StringSearcher searcher) {
		return searcher.matches(className);
	}
}
