2 * Copyright (c) 2009 The openGion Project.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 * either express or implied. See the License for the specific language
14 * governing permissions and limitations under the License.
16 package org.opengion.fukurou.business;
18 import org.opengion.fukurou.model.DataModel;
19 import org.opengion.fukurou.model.NativeType;
20 import static org.opengion.fukurou.system.HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring
21 import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring
23 import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04)
24 import java.util.concurrent.ConcurrentHashMap; // 6.4.3.1 (2016/02/12) refactoring
25 import java.util.Arrays;
28 * 業務ロジックを処理するためのテーブルモデルです。
30 * このテーブルモデルでは、オブジェクト生成時に、カラム配列、値配列を元に、内部データを生成し、
31 * その後は、行の追加や値の変更はできません。
33 * @og.rev 5.1.1.0 (2009/12/01) 新規作成
37 * @author Hiroki Nakamura
40 public class ArrayTableModel implements DataModel<String> {
42 private final String[] names;
43 private final String[][] vals;
44 private final String[] modTypes;
46 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */
47 private final ConcurrentMap<Integer,String[]> rtnMap = new ConcurrentHashMap<>() ; // 6.4.3.3 (2016/03/04) final化で、初期から作成しておきます。
50 * 引数に名前配列、値配列を指定したコンストラクター
54 * @throws IllegalArgumentException 引数の配列が不正な場合
56 public ArrayTableModel( final String[] nms, final String[][] vs ) {
57 this( nms, vs, null );
61 * 引数に名前配列、値配列、変更区分配列を指定したコンストラクター
63 * @og.rev 5.6.7.0 (2013/07/27) エラーメッセージを判りやすくする。
64 * @og.rev 5.7.2.3 (2014/01/31) vsのチェック条件を戻す
65 * @og.rev 5.7.3.1 (2014/02/14) nmsのチェック条件も戻す
70 * @throws IllegalArgumentException 引数の配列が不正な場合
72 public ArrayTableModel( final String[] nms, final String[][] vs, final String[] ms ) {
73 if( nms == null || nms.length == 0 ) {
74 final String errMsg = "引数の名前配列に、null は設定できません。";
75 throw new IllegalArgumentException( errMsg );
77 // 5.6.7.0 (2013/07/27) エラーメッセージを判りやすくする。
78 // 5.7.2.3 (2014/01/31) 結果0行でlength=0で通るようなのでvsのエラーチェック条件を戻す。
80 final String errMsg = "引数の値配列に、null は設定できません。";
81 throw new IllegalArgumentException( errMsg );
83 // 5.7.3.1 (2014/02/14) 5.7.2.3での戻しでは不十分だったのでこちらも戻す
84 // 6.0.0.1 (2014/04/25) These nested if statements could be combined
85 if( vs.length > 0 && ( vs[0] == null || vs[0].length == 0 || nms.length != vs[0].length ) ) {
86 final String errMsg = "名前配列と値配列のカラム数が異なります。" + CR
87 + " nms =" + Arrays.toString( nms ) + CR
88 + " vs[0] =" + Arrays.toString( vs[0] ) ;
89 throw new IllegalArgumentException( errMsg );
92 final int cols = nms.length;
93 names = new String[cols];
94 System.arraycopy( nms, 0, names, 0, cols );
96 final int rows = vs.length;
97 vals = new String[rows][cols];
98 for( int i=0; i<rows; i++ ) {
99 System.arraycopy( vs[i], 0, vals[i], 0, cols );
102 if( ms != null && ms.length > 0 ) {
103 if( vs.length == ms.length ) {
104 modTypes = new String[rows];
105 System.arraycopy( ms, 0, modTypes, 0, rows );
108 // 5.6.7.0 (2013/07/27) エラーメッセージを判りやすくする。
109 final String errMsg = "変更区分を指定する場合、値配列の行数と一致する必要があります。" + CR
110 + " 変更区分 行数 =" + ms.length + CR
111 + " 値配列 行数 =" + vs.length ;
112 throw new IllegalArgumentException( errMsg );
121 * rowで指定された行番号(インデックス番号)に行を追加します。
123 * 値配列をセットする場合は、以下の条件を満たす必要があります。
124 * 1.行番号は、0~(rowCount-1) の範囲
125 * 2.値配列は、not null、 かつ 1件以上
126 * 3.値配列の個数は、内部カラム数と同じ
128 * ここで登録した値は、内部の値配列と別管理されますので、セット後に、再びゲットしても
129 * ここでセットした値を取り出すことはできません。
130 * また、同じ行番号でセットした場合は、後でセットした値が有効です。
132 * ※ ここでの更新時に、modifyType は、設定されません。
133 * 必要であれば、setModifyType メソッドで個別に設定してください。
135 * ※ インデックス(row)とは、このArrayTableModel に持つ vals 配列の行のインデックスです。
136 * よって、オリジナルのDBTableModelの行番号ではありません。
138 * @og.rev 5.6.0.3 (2012/01/24) 変更された値を、書き戻す機能を追加します。
139 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
142 * @param rowNo 追加するインデックス
143 * @throws IllegalArgumentException 引数が1,2,3の条件を満たさない場合。
145 @Override // DataModel
146 public void setValues( final String[] inVals, final int rowNo ) {
147 if( rowNo < 0 || rowNo > getRowCount() ) {
148 final String errMsg = "引数のインデックスは、0~" + (getRowCount()-1) + " の間で指定してください。index=[" + rowNo + "]";
149 throw new IllegalArgumentException( errMsg );
151 else if( inVals == null || inVals.length == 0 ) {
152 final String errMsg = "引数の値配列に、null、または 0件配列は指定できません。index=[" + rowNo + "]";
153 throw new IllegalArgumentException( errMsg );
155 else if( inVals.length != names.length ) {
156 final String errMsg = "引数の値配列の個数と、内部カラム数が一致しません。"
157 + " index=[" + rowNo + "] : 引数個数=[" + inVals.length + "] != 内部カラム数=[" + names.length + "]";
158 throw new IllegalArgumentException( errMsg );
161 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
163 final int cols = names.length;
164 final String[] newVals = new String[cols];
165 System.arraycopy( inVals, 0, newVals, 0, cols );
167 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。初期化処理の場所も移動。
168 rtnMap.put( Integer.valueOf( rowNo ) , newVals );
172 * BizLogicで、データが変更された場合は、このMapで値の配列を返します。
173 * Mapのキーは、インデックス(row)のIntegerオブジェクトです。値は、設定された String配列です。
174 * なにも変更がされていなければ、空のConcurrentMapを返しましす。
176 * ※ インデックス(row)とは、このArrayTableModel に持つ vals 配列の行のインデックスです。
177 * よって、オリジナルのDBTableModelの行番号ではありません。
179 * @og.rev 5.6.0.3 (2012/01/24) 変更された値を、書き戻すためのMap<インデックス,値配列> を返します。
180 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
181 * @og.rev 6.4.3.3 (2016/03/04) 変更が無い場合は、nulllではなく、空のConcurrentMapを返しましす。
183 * @return 書き戻すためのMap<インデックス,値配列>
184 * @see AbstractBizLogic#isRequireTable()
187 public ConcurrentMap<Integer,String[]> getModifyVals() {
192 * カラム名に対応する カラム番号を返します。
194 * 特殊なカラムが指定された場合は、負の値を返します。
195 * 例えば、[KEY.カラム名]、[I]、[ROW.ID] など、特定の負の値を返します。
196 * また、カラム名が元のデータモデルに存在しない場合も、負の値か、
197 * Exception を返します。負の値なのか、Exception なのかは、
200 * @param columnName 値が参照されるカラム名
202 * @return 指定されたセルのカラム番号。存在しなければ、-1
203 * @throws IllegalArgumentException 引数のカラム名が null の場合
205 @Override // DataModel
206 public int getColumnNo( final String columnName ) {
207 if( columnName == null ) {
208 final String errMsg = "引数のカラム名に、null は設定できません。";
209 throw new IllegalArgumentException( errMsg );
213 for( int i=0; i<names.length; i++ ) {
214 if( columnName.equalsIgnoreCase( names[i] ) ) {
224 * カラム名配列に対応する カラム番号配列を返します。
226 * これは、#getColumnNo( String ) に対する 複数のカラム名を検索した
229 * @og.rev 6.8.6.0 (2018/01/19) 可変長引数から、通常配列に変更。
231 * @param clmNms 値が参照されるカラム名配列(可変長引数)
233 * @return 指定されたセルのカラム番号配列。
236 // public int[] getColumnNos( final String... clmNms ) {
237 public int[] getColumnNos( final String[] clmNms ) {
238 if( clmNms == null || clmNms.length == 0 ) { return new int[0]; } // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
240 int[] clmNos = new int[clmNms.length];
241 for( int j=0; j<clmNms.length; j++ ) {
243 for( int i=0; i<names.length; i++ ) {
244 if( clmNms[j].equalsIgnoreCase( names[i] ) ) {
261 @Override // DataModel
262 public String[] getNames() {
263 return names.clone();
267 * 指定のカラム名引数に相当するデータを2重配列で返します。
269 * @og.rev 6.8.5.0 (2018/01/09) 新規追加
271 * @param clmNms 値が参照されるカラム名配列(可変長引数)
273 * @return 指定された名引数に相当するデータの2重配列
276 protected String[][] getValues( final String... clmNms ) {
277 final int[] clmNos = getColumnNos( clmNms );
279 final String[][] rtns = new String[vals.length][clmNos.length];
281 for( int row=0; row<vals.length; row++ ) {
282 for( int j=0; j<clmNos.length; j++ ) {
283 final int col = clmNos[j];
284 rtns[row][col] = vals[row][col];
292 * row にあるセルの属性値を配列で返します。
294 * @param row 値が参照される行
296 * @return 指定されたセルの属性値配列
299 @Override // DataModel
300 public String[] getValues( final int row ) {
301 return vals[row].clone();
305 * row および clm にあるセルの属性値をStringに変換して返します。
307 * @param row 値が参照される行
308 * @param clm 値が参照される列
312 @Override // DataModel
313 public String getValue( final int row, final int clm ) {
314 return vals[row][clm];
318 * row および clm にあるセルの属性値をStringに変換して返します。
320 * @param row 値が参照される行
321 * @param clm 値が参照される列(キー)
326 public String getValue( final int row, final String clm ) {
327 return vals[row][getColumnNo( clm )];
336 @Override // DataModel
337 public int getRowCount() {
342 * row 単位に変更されたタイプ(追加/変更/削除)を返します。
343 * タイプは始めに一度登録するとそれ以降に変更はかかりません。
344 * つまり、始めに 追加で作成したデータは、その後変更があっても追加のままです。
345 * なにも変更されていない場合は、""(ゼロストリング)を返します。
347 * @param row 値が参照される行
351 @Override // DataModel
352 public String getModifyType( final int row ) {
353 return modTypes == null ? "" : modTypes[row];
357 * row 単位に変更タイプ(追加/変更/削除)をセットします。
358 * このメソッドでは、データのバックアップは取りません。
359 * タイプは始めに一度登録するとそれ以降に変更はかかりません。
360 * なにも変更されていない場合は、""(ゼロストリング)の状態です。
362 * @og.rev 6.7.9.1 (2017/05/19) インターフェースの見直しにより、追加
364 * @param row 値が参照される行
365 * @param modType 変更タイプ(追加/変更/削除)
368 @Override // DataModel
369 public void setModifyType( final int row , final String modType ) {
370 if( modTypes[row].isEmpty() ) { modTypes[row] = modType; }
374 * clm のNativeタイプを返します。
375 * Nativeタイプはorg.opengion.fukurou.model.NativeTypeで定義されています。
377 * @og.rev 5.1.8.0 (2010/07/01) NativeType#getType(String) のメソッドを使用するように変更。
379 * @param clm 値が参照される列
382 * @see org.opengion.fukurou.model.NativeType
384 @Override // DataModel
385 public NativeType getNativeType( final int clm ) {
386 return NativeType.getType( vals[0][clm] );
390 * このオブジェクトの文字列表記を返します。
393 * @og.rev 5.6.7.0 (2013/07/27) 新規追加
397 * @see java.lang.Object#toString()
400 public String toString() {
401 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
403 buf.append( "NAMES=" ).append( Arrays.toString( names ) ).append( CR )
404 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
405 .append( " COL_LEN=" ).append( names == null ? -1 : names.length ).append( CR )
406 .append( " ROW_LEN=" ).append( vals == null ? -1 : vals.length ).append( CR ) ;
408 return buf.toString();