001    /*
002     * Copyright (c) 2009 The openGion Project.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013     * either express or implied. See the License for the specific language
014     * governing permissions and limitations under the License.
015     */
016    package org.opengion.hayabusa.html;
017    
018    import org.opengion.fukurou.util.StringUtil ;
019    
020    import java.util.Map;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.ArrayList;
024    import java.util.Arrays;
025    
026    /**
027     * String[] 型キーにカラ??の連想記?を用?、クロス?データを管?るクラスです?
028     *
029     * クロス?では、カラ??が???タとして与えられる為、このクラス?で?
030     * ?カラ??の連想記?(Map)??タを作?し?実際の行データ登録時に??タ?
031     * 設定して?す?
032     * 取り出すとき?、?に取り出すことを?慮して???ArrayList)??タに
033     * 共有して?オブジェクトを取り出します?
034     *
035     * こ?実??同期化されません?
036     *
037     * @og.rev 3.5.4.0 (2003/11/25) 新規作?
038     * @og.group 画面表示
039     *
040     * @version  4.0
041     * @author   Kazuhiko Hasegawa
042     * @since    JDK5.0,
043     */
044    public final class CrossMap {
045            private final Map<String,String[]> row = new HashMap<String,String[]>() ;
046            private final Map<String,Integer>  clm = new HashMap<String,Integer>() ;
047            private final List<String[]> list = new ArrayList<String[]>();
048            private final int headCount;
049            private final int sumCount;
050            private final int totalCols;
051    
052            /**
053             * カラ?(クロス?部)を与えて新しく作?するコンストラクター
054             *
055             * クロス?を行うカラ?のみセ?します?
056             * 行?クロス?部のヘッ??キーは、引数の配?の?で、設定されます?
057             * こ?行?ヘッ??部となるデータは、addData 時にセ?します?
058             *
059             * @param       clmData         クロス?部のカラ?配?
060             * @param       headCount       HEADカラ??数
061             * @param       sumCount        合計カラ??数
062             */
063            public CrossMap( final String[] clmData, final int headCount, final int sumCount ) {
064                    if( headCount <= 0 ) {
065                            String errMsg = "headCount は、ROWカラ?含?め??1以上?です?";
066                            throw new IllegalArgumentException( errMsg );
067                    }
068    
069                    this.headCount = headCount;
070                    this.sumCount  = sumCount;
071                    int clmNum = clmData.length;
072                    totalCols = headCount + clmNum * sumCount;
073                    for( int i=0; i<clmNum; i++ ) {
074                            clm.put( clmData[i],Integer.valueOf( i ) );
075                    }
076            }
077    
078            /**
079             * クロス???なる検索結果の行データを登録します?
080             *
081             * クロス?を行うカラ?のみ,セ?します?
082             * 行?ヘッ??部となるデータは、rowKeys と headCount で?します?
083             * 行?クロス?部のヘッ??キーは、clmKey で?し、?部で、?カラ?して
084             * 割り当てられます?割り当て?カラ??)は、コンストラクタでの clmData の
085             * 配?の?です?
086             *
087             * @param       rowKeys 行データの配?( ?~headCount の値が行?キーとなります?)
088             */
089            public void add( final String[] rowKeys ) {
090                    if( rowKeys.length < headCount + 1 + sumCount) {
091                            String errMsg = "?? rowKeys の個数が不正です? rowKeys には、clmKey と data が?です?"
092                                                    + " rowKeys=" + StringUtil.array2csv( rowKeys ) ;       // 5.1.8.0 (2010/07/01) errMsg 修正
093                            throw new ArrayIndexOutOfBoundsException( errMsg );
094                    }
095    
096                    // 3.5.6.6 (2004/08/23) 修正
097                    String clmKey = rowKeys[headCount];                             // カラ??のクロス?部のキー(ヘッ??)
098                    String[] data = new String[sumCount];   // クロス?表の値
099                    for( int i=0; i<sumCount; i++ ) {
100                            data[i] = rowKeys[headCount+1+i];
101                    }
102    
103                    String rowKey ;
104                    // 3.5.6.6 (2004/08/23) 修正
105                    if( headCount == 1 ) { rowKey = rowKeys[0]; }
106                    else {
107                            StringBuilder rKey = new StringBuilder();
108                            for( int i=0; i<headCount; i++ ) {
109                                    rKey.append( rowKeys[i] );
110                                    rKey.append( "_" );
111                            }
112                            rowKey = rKey.toString();
113                    }
114                    String[] clmData = row.get( rowKey );
115                    if( clmData == null ) {
116                            // 行データ+クロス行データ
117                            clmData = new String[totalCols];
118                            Arrays.fill( clmData,"" );
119                            for( int i=0; i<headCount; i++ ) {
120                                    clmData[i] = rowKeys[i];
121                            }
122                            list.add( clmData );    // 生??ArrayList にセーブします?
123                    }
124    
125                    for( int i=0; i<sumCount; i++ ) {
126                            int no = headCount + (clm.get( clmKey )).intValue()*sumCount+i; // 列番号
127                            clmData[no] = data[i];
128                    }
129                    row.put( rowKey,clmData );      // ArrayList と同じオブジェクトを検索用のMapにもセ?する?
130            }
131    
132            /**
133             * クロス?結果の?行?列データを返します?
134             *
135             * @param       row ??行番号( 0 .. getSize()-1 )
136             *
137             * @return      列データ配?
138             */
139            public String[] get( final int row ) {
140                    return list.get( row );
141            }
142    
143            /**
144             * クロス?結果の行数を返します?
145             *
146             * @return   行数を返します?
147             */
148            public int getSize() {
149                    return list.size();
150            }
151    }