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    }