package jp.ac.takushoku_u.cs;

/**
* StringMatrixクラスでは文字列を要素にもつマトリクスを扱います。
* 主に出力のために扱います。
* @version 1.1
* @author 笠島 裕史(Kasajima Hiroshi)
* @see jp.ac.takushoku_u.cs.ArithmeticMatrix
* @see jp.ac.takushoku_u.cs.BooleanMatrix
*/
/*
* 最終更新日 2004年11月24日
*/
public class StringMatrix extends Matrix{

/**
* マトリクスをクリアするときの値
*/
	private static final String MATRIX_CLEAR_VALUE = "";

/**
* 判定値
*/
	private static final String MATRIX_VALUE_FALSE = "";


/**
* 設定されているサイズのデータ保存用の2次元配列と行名、列名を入れる配列を生成します。<BR>
* 生成された2次元配列は全てfalseで初期化されます。
* 行名と列名は行番号と列番号で設定されます。
*/
	public StringMatrix(){
		super();
		clearMatrix();
	}

/**
* 指定された行サイズと列サイズを元にデータ保存用の2次元配列と行名、列名を入れる配列を生成します。<BR>
* 生成された2次元配列は全てfalseで初期化されます。
* 行名と列名は行番号と列番号で設定されます。
* @param rowSize 指定する行サイズ
* @param colSize 指定する列サイズ
* @exception NegativeMatrixSizeException 負のサイズのマトリクスが生成しようとした場合
*/
	public StringMatrix(int rowSize, int colSize){
		super(rowSize, colSize);
		clearMatrix();
	}
	
/**
* 指定された行サイズと列サイズを元にデータ保存用の2次元配列と行名、列名を入れる配列を生成し、
* 指定された番号から順に行名と列名を初期化します。<BR>
* 生成された2次元配列は全てfalseで初期化されます。
* 行名と列名は nameNumber で指定された番号から順に設定されます。
* @param rowSize 指定する行サイズ
* @param colSize 指定する列サイズ
* @param nameNumber 行名および列名の開始番号
* @exception NegativeMatrixSizeException 負のサイズのマトリクスが生成しようとした場合
*/
	public StringMatrix(int rowSize, int colSize, int nameNumber){
		super(rowSize, colSize, nameNumber);
		clearMatrix();
	}
	
/**
* 指定された行サイズ、列サイズ、行名、列名を元にデータ保存用の2次元配列と行名、列名を入れる配列を生成します。<BR>
* 生成された2次元配列は全てfalseで初期化されます。
* @param rowSize 指定する行サイズ
* @param colSize 指定する列サイズ
* @param rowName 指定する行名
* @param colName 指定する列名
* @exception NegativeMatrixSizeException 負のサイズのマトリクスが生成しようとした場合
* @exception IndexOutOfBoundsException コピーによって配列の境界を越えたデータのアクセスが生じた場合
* @exception NullPointerException  rowName または colName が null の場合
*/
	public StringMatrix(int rowSize, int colSize, String[] rowName, String[] colName){
		super(rowSize, colSize);
		clearMatrix();
		
		//行名および列名のコピー
		nameRowCopy(rowName);
		nameColCopy(colName);
	}
	
/**
* 指定された2次元配列を元にデータ保存用の2次元配列と行名、列名を入れる配列を生成します。<BR>
* 行名と列名は行番号と列番号で設定されます。
* @param originalMatrix 指定する2次元配列
* @exception IndexOutOfBoundsException コピーによって配列の境界を越えたデータのアクセスが生じた場合
* @exception NullPointerException  originalMatrix が null の場合
*/
	public StringMatrix(String[][] originalMatrix){
		super(originalMatrix.length, originalMatrix[0].length);
		
		//マトリクスのコピー
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				setCell(i, j, originalMatrix[i][j]);
			}
		}
	}

/**
* 指定された2次元配列を元にデータ保存用の2次元配列と行名、列名を入れる配列を生成し、
* 指定された番号から順に行名と列名を初期化します。<BR>
* 行名と列名は nameNumber で指定された番号から順に設定されます。
* @param originalMatrix 指定する2次元配列
* @param nameNumber 行名および列名の開始番号
* @exception IndexOutOfBoundsException コピーによって配列の境界を越えたデータのアクセスが生じた場合
* @exception NullPointerException  originalMatrix が null の場合
*/
	public StringMatrix(String[][] originalMatrix, int nameNumber){
		super(originalMatrix.length, originalMatrix[0].length, nameNumber);
		
		//マトリクスのコピー
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				setCell(i, j, originalMatrix[i][j]);
			}
		}
	}

/**
* 指定された2次元配列、行名、列名を元にデータ保存用の2次元配列と行名、列名を入れる配列を生成します。
* @param originalMatrix 指定する2次元配列
* @param rowName 指定する行名
* @param colName 指定する列名
* @exception IndexOutOfBoundsException コピーによって配列の境界を越えたデータのアクセスが生じた場合
* @exception NullPointerException rowName , colName または originalMatrix が null の場合
*/
	public StringMatrix(String[][] originalMatrix, String[] rowName, String[] colName){
		super(originalMatrix.length, originalMatrix[0].length);
		
		//マトリクスのコピー
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				setCell(i, j, originalMatrix[i][j]);
			}
		}
		
		//行名および列名のコピー
		nameRowCopy(rowName);
		nameColCopy(colName);
	}

/**
* 保持された要素を変更せずにマトリクスの大きさを変更します。
* マトリクスを小さくする場合は指定した要素より大きい部分がなくなります。
* 大きくする場合大きくされた部分は初期値で初期化され、
* 行名と列名はそれぞれ行番号と列番号になります。
* @param rowLength 行サイズ
* @param colLength 列サイズ
* @exception NegativeMatrixSizeException 負のサイズのマトリクスが生成しようとした場合
*/
	public void reSizeMatrix(int rowLength, int colLength){
		int r = getRowLength();
		int c = getColLength();
		super.reSizeMatrix(rowLength, colLength);
		
		
		//マトリクスの要素を入れる
		for (int i = 0; i < rowLength; i++){
			if(i >= r){
				setRowName(i, i+"");
			}
			for (int j = 0; j < colLength; j++){
				if(j >= c){
					setColName(j, j+"");
				}
				if((i >= r) || (j >= c)){
					setCell(i, j, MATRIX_CLEAR_VALUE);
				}
			}
		}
	}

/**
* 指定された1点へ値を設定します。
* @param row 指定行番号
* @param col 指定列番号
* @param ch 設定値
* @exception NotElementException 指定した点が存在しない場合
*/
	public void setCell(int row,int col,String ch){
		if (isMatrixEntityPoint(row, col)){
			super.setCell(row,col,ch);
		}
		else{
			throw new NotElementException("Point(" + row + "," + col + ")");
		}
	}

/**
* マトリクスに他のマトリクスの要素、行名、列名の全てをコピーします。<BR>
* コピー元のマトリクスサイズと一致しない場合はコピー元のマトリクスサイズに変更し、コピーを行います。
* @param originalMatrix コピー元のマトリクス
* @see #matrixCopy(StringMatrix originalMatrix, int baseRow, int baseCol, int copyRow,int copyCol, int rowLength, int colLength)
*/
	public void matrixCopy(StringMatrix originalMatrix){
		super.matrixCopy(originalMatrix);
	}
	
/**
* 指定位置で開始する指定要素からコピー先のマトリクスの指定位置に要素をコピーします。<BR>
* コピー元の要素( baseRow , baseCol )で指定された要素を開始位置とし、rowLength 行 colLength 列分だけ
* 要素( copyRow , copyCol )から指定される要素から始まる要素にコピーを行います。
* コピー先の範囲に当てはまらない要素と行名、列名は変更されません。
* @param originalMatrix コピー元のマトリクス
* @param baseRow コピー元のマトリクスに対するコピーの行開始位置
* @param baseCol コピー元のマトリクスに対するコピーの列開始位置
* @param copyRow コピーされる行開始位置
* @param copyCol コピーされる列開始位置
* @param rowLength コピーを行う行の要素数
* @param colLength コピーを行う列の要素数
* @exception SetValueOutOfBoundsException コピー先が存在しない範囲にあたる場合
* @see #matrixCopy(StringMatrix originalMatrix)
*/
	public void matrixCopy(StringMatrix originalMatrix, int baseRow, int baseCol, int copyRow,
		int copyCol, int rowLength, int colLength){
			super.matrixCopy(originalMatrix, baseRow, baseCol, copyRow,
				copyCol, rowLength, colLength);
	}
	
/**
* マトリクスに存在する要素全てに""を入れます。
*/
	public void clearMatrix(){
		for (int i = 0 ; i < getRowLength() ; i++){
			for (int j = 0 ; j < getColLength() ; j++){
				setCell(i, j, MATRIX_CLEAR_VALUE);
			}
		}
	}
	
/**
* 指定された1点の値を返します。
* @param row 指定行番号
* @param col 指定列番号
* @return 指定した点の値
* @exception NotElementException 指定された点が存在しない場合
*/
	public String getCell(int row, int col){
		if (isMatrixEntityPoint(row, col)){
			String s = (String)getObjectCell(row,col);
			return s;
		}
		else{
			throw new NotElementException("point(" + row + "," + col + ")");
		}
	}
	
/**
* マトリクスに存在する要素のうち、要素が空白でない要素の数を返します。
* @return 要素数
*/
	public int getElement(){
		int element = 0;
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
				if (getCell(i, j) != MATRIX_VALUE_FALSE){
					element = element + 1;
				}
			}
		}
		return element;
	}
	
/**
* StringMatrixをMatrix型に変換します。
* 変換されたマトリクスには行名と列名は引き継がれます。
* @return 変換されたMatrix
* @exception NumberFormatException 文字列が構文解析可能な double 値を含まない場合
* @see #toBooleanMatrix()
*/
	public ArithmeticMatrix toArithmeticMatrix(){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
					returnMatrix.setCell(i, j, Double.valueOf(getCell(i, j)));
				
			}
		}
		return returnMatrix;
	}
	
/**
* StringMatrixをBooleanMatrix型に変換します。
* 文字列"true"に等しい(大文字と小文字は区別しない)場合はtrueに、それ以外の文字列はfalseになります。
* 変換されたマトリクスには行名と列名は引き継がれます。
* @return 変換されたMatrix
* @see #toArithmeticMatrix()
*/
	public BooleanMatrix toBooleanMatrix(){
		BooleanMatrix returnMatrix = new BooleanMatrix(getRowLength(), getColLength(),
			getRowNameArray(), getColNameArray());
		for (int i = 0; i < getRowLength(); i++){
			for (int j = 0; j < getColLength(); j++){
					returnMatrix.setCell(i, j, Boolean.valueOf(getCell(i, j)));
			}
		}
		return returnMatrix;
	}
	
/**
* 2つのマトリクスのサイズが同じかチェックします。
* @param compareMatrix 調べるマトリクス
* @return サイズが同じであればTrueを、違う場合はFalseを返します。
*/
	public boolean isSameMatrixSize(StringMatrix compareMatrix){
		return getRowLength() == compareMatrix.getRowLength()
			&& getColLength() == compareMatrix.getColLength();
	}
	
/**
* マトリクスの要素を2次元配列で返します。
* @return 要素の2次元配列
*/
	public String[][] getMatrix(){
		String st[][] = new String[getRowLength()][getColLength()];
		Object o[][] = new Object[getRowLength()][getColLength()];
		o = getObjectMatrix();
		for(int i=0; i < getRowLength(); i++){
			for(int j=0; j < getColLength(); j++){
				st[i][j] = (String)o[i][j];
			}
		}
		return st;
	}
}