/*
 * blancoDb
 * Copyright (C) 2004-2005 Yasuo Nakanishi
 * 
 * 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.
 */
package blanco.db.collector;

import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import blanco.ig.expander.NameAdjuster;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;

/**
 * @author Yasuo Nakanishi
 */
public class TypeFinder {
    private Map _parameterList = new Hashtable();

    private NameAdjuster _adjuster = new NameAdjuster();

    private Type _type = null;

    private String _callStatement = null;

    public TypeFinder(Iterator parameters) {
        Value value = null;
        while (parameters.hasNext()) {
            value = (Value) parameters.next();
            _parameterList.put(value.getName(), value);
        }
    }

    public boolean findType(String parameter) {
        boolean result = true;
        String[] values = parameter.split("\\.");
        Value value = (Value) _parameterList.get(values[0]);
        String[] statements = new String[values.length];

        if (value == null) {
            String message = "パラメータが見つかりませんでした。パラメータ名:" + parameter;
            throw new RuntimeException(message);
        }

        Type type = value.getType();
        statements[0] = values[0];
        Method method = null;
        try {
            for (int i = 1; i < values.length; i++) {
                method = getMethod(value.getType(), values[i]);
                statements[i] = method.getName() + "()";
                type = new Type(method.getReturnType());
                value = new Value(type, values[i]);
            }
            _type = type;
            result = true;
        } catch (Exception e) {
            result = false;
        }
        _callStatement = createCallStatement(statements);
        return result;
    }

    private String createCallStatement(String[] statements) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < statements.length; i++) {
            if (i > 0) {
                sb.append(".");
            }
            sb.append(statements[i]);
        }
        return sb.toString();
    }

    public Type getType() {
        return _type;
    }

    public String getCallStatment() {
        return _callStatement;
    }

    public Method getMethod(Type type, String name) throws SecurityException,
            ClassNotFoundException {
        Method result = null;
        Method[] methods = getMethods(type);
        String methodName = "";

        methodName = name;
        for (int i = 0; i < methods.length; i++) {
            if (methods[i].getName().equals(methodName)) {
                result = methods[i];
                return result;
            }
        }

        methodName = _adjuster.getMethodName("get", name);
        for (int i = 0; i < methods.length; i++) {
            if (methods[i].getName().equals(methodName)) {
                result = methods[i];
                break;
            }
        }
        return result;
    }

    public Method[] getMethods(Type type) throws SecurityException,
            ClassNotFoundException {
        return Class.forName(type.getFullName()).getMethods();
    }

}