package com.jware.util.object;

/**
 *  PrimaryKeyを表現するクラス
 *  PrimaryKeyクラスから継承して、ObjectClass属性を追加する。
 *  IdentityのequalsメソッドにObjectClassとPrimaryKeyの値両方を比較する。
 */
public class Identity {
    /**
     * PrimaryKey値配列
     */
    private Object[] pkValues = null;
    /**
     * PrimaryKey名配列
     */
    private String[] pkNames = null;
    /**
     * オブジェクトのクラス
     */
    private Class objectsClass = null;
    /**
     * 文字列表現
     */
    private transient String stringRepresentation = null;
    /**
     * PrimaryKeyの個数
     */
    private int pkValueLength = 0;

    /**
     *  コンストラクタ
     * primary key names , primary key values ,classにより、
     * Identityインスタンスを作る。
     * @param aClass　表現するオブジェクトのタイプ
     * @param pkNames　primary key names
     * @param pkValues primary key values
     */
    public Identity(Class aClass, String[] pkNames, Object[] pkValues) {
        if (pkNames == null || pkValues == null) {
            throw new java.lang.IllegalArgumentException(
                "PKValues または PKNamesはNULLです");
        }
        if (pkNames.length != pkValues.length) {
            throw new java.lang.IllegalArgumentException(
                "PKValuesの長さはPKNamesの長さと一緒ではない");
        }
        this.objectsClass = aClass;
        this.pkNames = pkNames;
        this.pkValues = pkValues;
        this.pkValueLength = pkValues.length;
    }

    /**
     * [機 能]クラスタイプを戻る
     * @return java.lang.Class
     */
    public Class getObjectsClass() {
        return objectsClass;
    }

    /**
     * 文字列の表現式を戻る
     * @return java.lang.String
     */
    public String toString() {
        if (stringRepresentation == null) {
            StringBuffer buf = new StringBuffer();
            buf.append(objectsClass.getName());
            for (int i = 0; i < pkValueLength; i++) {
                buf.append((i == 0) ? "{" : ",");
                buf.append(pkNames[i]);
                buf.append(':');
                buf.append(pkValues[i]);
            }
            buf.append('}');
            stringRepresentation = buf.toString();
        }
        return stringRepresentation;
    }

    /**
     * PrimaryKeyデータを戻る
     * @return Object[]
     */
    public Object[] getPrimaryKeyValues() {
        return pkValues;
    }

    /**
     * PrimaryKey名を取得する
     * @return String[] PK名の配列
     */
    public String[] getPrimaryKeyNames() {
        return pkNames;
    }

    /**
     * 比較メソッド
     * クラスタイプとpkValuesを比較して、一緒であれば、TRUEを戻る。
     *
     * @param o オブジェクト
     * @return　trueの場合  o equals this
     */
    public boolean equals(Object o) {
        boolean result = false;
        if (o instanceof Identity) {
            Identity id = (Identity)o;
            Object otherPkValues[] = id.pkValues;
            result = this.getObjectsClass().equals(id.getObjectsClass());
            result = result && (pkValueLength == otherPkValues.length);
            for (int i = 0; result && i < pkValueLength; i++) {
                result = (pkValues[i] == null) ? (otherPkValues[i] == null)
                    : pkValues[i].equals(otherPkValues[i]);
            }
        } else {
            result = false;
        }
        return result;
    }

    /**
     * Hashcodeを計算する。
     * PrimaryKeyとクラスタイプを文字列に変換して,hashcodeを計算する。そして、pkValuesと
     * クラスタイプは一緒であれば、hashCodeも一緒、equalsもtrueを戻る。
     * @return hashCode
     */
    public int hashCode() {
        return toString().hashCode();
    }
}